diff --git a/ISSUE_UI_SCREENSHOT_IMPROVEMENT.md b/ISSUE_UI_SCREENSHOT_IMPROVEMENT.md
new file mode 100644
index 00000000000..251d9a8818d
--- /dev/null
+++ b/ISSUE_UI_SCREENSHOT_IMPROVEMENT.md
@@ -0,0 +1,49 @@
+# Improve UI screenshot generation for PR documentation
+
+## Problem
+
+The current approach to generating screenshots for UI components using Python/PIL produces white/blank images that don't accurately represent the Eclipse UI.
+
+## Proposed Solutions
+
+### 1. SWT Snippet Approach
+Create small SWT snippets that can render the UI components. However, this requires complex setup for many components that depend on Eclipse platform infrastructure.
+
+### 2. MCP Server with Eclipse Install (Recommended)
+Create a Model Context Protocol (MCP) server that includes a full Eclipse installation. This would allow:
+- Programmatic access to Eclipse UI components
+- Automated screenshot capture of actual rendered UI
+- Better representation of Eclipse styling and themes
+- Reusable infrastructure for future UI documentation
+
+## Context
+
+This issue was identified while implementing the Source Lookups preference page (see related PR for #2073). The generated screenshot using Python/PIL doesn't accurately show how the preference page would look in a real Eclipse environment.
+
+## Benefits of MCP Server Approach
+
+- **Accuracy**: Screenshots show actual Eclipse UI rendering with proper fonts, colors, and styling
+- **Reusability**: Can be used for all future UI-related PRs and documentation
+- **Automation**: Can be integrated into CI/CD pipeline for automatic screenshot generation
+- **Quality**: Better documentation quality improves contributor and user experience
+
+## Implementation Ideas
+
+1. Create a headless Eclipse installation in a container
+2. Build an MCP server that can:
+ - Launch Eclipse workbench programmatically
+ - Navigate to specific UI components (dialogs, preference pages, views, etc.)
+ - Capture screenshots using SWT/platform APIs
+ - Return screenshots as base64 or file paths
+3. Integrate with Copilot workflow for automatic screenshot generation
+
+## Labels
+
+- `enhancement`
+- `documentation`
+- `tooling`
+
+## Related
+
+- Source Lookups preference page PR
+- Issue #2073
diff --git a/source_lookups_preference_page.png b/source_lookups_preference_page.png
new file mode 100644
index 00000000000..9abf876f961
Binary files /dev/null and b/source_lookups_preference_page.png differ
diff --git a/ui/org.eclipse.pde.core/plugin.xml b/ui/org.eclipse.pde.core/plugin.xml
index 9d0eb5530f7..494c61532cf 100644
--- a/ui/org.eclipse.pde.core/plugin.xml
+++ b/ui/org.eclipse.pde.core/plugin.xml
@@ -430,6 +430,9 @@
+
diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/ExternalPluginSourcePathLocator.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/ExternalPluginSourcePathLocator.java
new file mode 100644
index 00000000000..8e09bca0a0f
--- /dev/null
+++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/ExternalPluginSourcePathLocator.java
@@ -0,0 +1,446 @@
+/*******************************************************************************
+ * Copyright (c) 2025 Christoph Läubrich and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Christoph Läubrich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.internal.core;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.equinox.p2.metadata.IArtifactKey;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.metadata.MetadataFactory;
+import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
+import org.eclipse.equinox.p2.metadata.Version;
+import org.eclipse.equinox.p2.query.IQueryResult;
+import org.eclipse.equinox.p2.query.QueryUtil;
+import org.eclipse.equinox.p2.repository.IRepository;
+import org.eclipse.equinox.p2.repository.IRepositoryManager;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRequest;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
+import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.pde.core.IPluginSourcePathLocator;
+import org.eclipse.pde.core.plugin.IPluginBase;
+import org.eclipse.pde.core.target.ITargetDefinition;
+import org.eclipse.pde.core.target.ITargetHandle;
+import org.eclipse.pde.core.target.ITargetLocation;
+import org.eclipse.pde.core.target.ITargetPlatformService;
+import org.eclipse.pde.internal.core.copyfrom.oomph.P2Index;
+import org.eclipse.pde.internal.core.copyfrom.oomph.P2Index.Repository;
+import org.eclipse.pde.internal.core.target.IUBundleContainer;
+import org.eclipse.pde.internal.core.target.P2TargetUtils;
+import org.eclipse.pde.internal.core.target.TargetPlatformService;
+import org.eclipse.pde.internal.ui.IPreferenceConstants;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+
+/**
+ * A plugin source path locator that queries external repositories and the
+ * Eclipse index for source bundles based on the configured preferences.
+ *
+ * This locator checks the Source Lookups preference page settings and performs
+ * lookups according to the configured order.
+ *
+ *
+ * @since 3.17
+ */
+public class ExternalPluginSourcePathLocator implements IPluginSourcePathLocator {
+
+ // Source lookup strategy identifiers
+ private static final String STRATEGY_REPOSITORIES = "REPOSITORIES"; //$NON-NLS-1$
+ private static final String STRATEGY_TARGETS = "TARGETS"; //$NON-NLS-1$
+ private static final String STRATEGY_INDEX = "INDEX"; //$NON-NLS-1$
+ private static final String STRATEGY_SITES = "SITES"; //$NON-NLS-1$
+
+ private P2Index p2Index;
+
+ @Override
+ public IPath locateSource(IPluginBase plugin) {
+ IPreferenceStore store = PDEPlugin.getDefault().getPreferenceStore();
+
+ // Check if source lookup is enabled
+ if (!store.getBoolean(IPreferenceConstants.SOURCE_LOOKUP_ENABLED)) {
+ return null;
+ }
+
+ // Get the lookup order
+ List lookupOrder = getLookupOrder(store);
+
+ // Execute lookups in the configured order
+ for (String strategy : lookupOrder) {
+ IPath result = null;
+ switch (strategy) {
+ case STRATEGY_REPOSITORIES:
+ result = searchInRepositories(plugin, getConfiguredRepositories(store));
+ break;
+ case STRATEGY_TARGETS:
+ result = searchInTargets(plugin, getSelectedTargets(store));
+ break;
+ case STRATEGY_INDEX:
+ result = queryEclipseIndex(plugin);
+ break;
+ case STRATEGY_SITES:
+ result = queryAvailableSoftwareSites(plugin);
+ break;
+ default:
+ // Unknown strategy, skip
+ break;
+ }
+
+ if (result != null) {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the configured lookup order from preferences.
+ *
+ * @param store the preference store
+ * @return the list of strategy identifiers in order
+ */
+ private List getLookupOrder(IPreferenceStore store) {
+ String order = store.getString(IPreferenceConstants.SOURCE_LOOKUP_ORDER);
+ if (order == null || order.trim().isEmpty()) {
+ // Use default order
+ return Arrays.asList(STRATEGY_REPOSITORIES, STRATEGY_TARGETS, STRATEGY_INDEX, STRATEGY_SITES);
+ }
+ return Arrays.asList(order.split(",")); //$NON-NLS-1$
+ }
+
+ /**
+ * Searches for the source bundle in the configured repositories.
+ *
+ * @param plugin the plugin to locate sources for
+ * @param repositories the list of repository URLs
+ * @return the path to the source bundle or null if not found
+ */
+ private IPath searchInRepositories(IPluginBase plugin, List repositories) {
+ if (repositories == null || repositories.isEmpty()) {
+ return null;
+ }
+
+ String pluginId = plugin.getId();
+ String sourcePluginId = pluginId + ".source"; //$NON-NLS-1$
+ String pluginVersion = plugin.getVersion();
+
+ // Loop through all configured repository URLs
+ for (String repositoryURL : repositories) {
+ try {
+ // Try to download the source bundle from this repository
+ URI repoURI = URI.create(repositoryURL.trim());
+ IPath result = downloadArtifact(repoURI, sourcePluginId, pluginVersion);
+ if (result != null) {
+ // Found and downloaded successfully
+ return result;
+ }
+ } catch (Exception e) {
+ // Log and continue to next repository
+ PDECore.log("Failed to search for source in repository " + repositoryURL + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Searches for the source bundle in the specified target platforms.
+ *
+ * @param plugin the plugin to locate sources for
+ * @param selectedTargets the list of selected target platform names
+ * @return the path to the source bundle or null if not found
+ */
+ private IPath searchInTargets(IPluginBase plugin, List selectedTargets) {
+ if (selectedTargets == null || selectedTargets.isEmpty()) {
+ return null;
+ }
+
+ String pluginId = plugin.getId();
+ String sourcePluginId = pluginId + ".source"; //$NON-NLS-1$
+ String pluginVersion = plugin.getVersion();
+
+ try {
+ // Get the target platform service
+ ITargetPlatformService service = TargetPlatformService.getDefault();
+ if (service == null) {
+ return null;
+ }
+
+ // Get all available target definitions
+ ITargetHandle[] targetHandles = service.getTargets(null);
+ if (targetHandles == null) {
+ return null;
+ }
+
+ // Loop through all target handles
+ for (ITargetHandle targetHandle : targetHandles) {
+ try {
+ ITargetDefinition targetDef = targetHandle.getTargetDefinition();
+ if (targetDef == null || targetDef.getName() == null) {
+ continue;
+ }
+
+ // Check if this target is in the selected list
+ if (!selectedTargets.contains(targetDef.getName())) {
+ continue;
+ }
+
+ // Get all target locations from this target
+ ITargetLocation[] locations = targetDef.getTargetLocations();
+ if (locations == null) {
+ continue;
+ }
+
+ // Loop through locations and look for IUBundleContainer (IU locations)
+ for (ITargetLocation location : locations) {
+ if (location instanceof IUBundleContainer) {
+ IUBundleContainer iuLocation = (IUBundleContainer) location;
+
+ // Get the repository URIs from this IU location
+ List repositories = iuLocation.getRepositories();
+ if (repositories == null || repositories.isEmpty()) {
+ continue;
+ }
+
+ // Search each repository for the source bundle
+ for (URI repoURI : repositories) {
+ IPath result = downloadArtifact(repoURI, sourcePluginId, pluginVersion);
+ if (result != null) {
+ // Found and downloaded successfully
+ return result;
+ }
+ }
+ }
+ }
+ } catch (CoreException e) {
+ // Log and continue to next target
+ PDECore.log("Failed to process target definition: " + e.getMessage()); //$NON-NLS-1$
+ }
+ }
+ } catch (Exception e) {
+ // Log but don't fail - this is just one lookup strategy
+ PDECore.log(e);
+ }
+
+ return null;
+ }
+
+ /**
+ * Queries the Eclipse index for the source bundle.
+ *
+ * @param plugin the plugin to locate sources for
+ * @return the path to the source bundle or null if not found
+ */
+ private IPath queryEclipseIndex(IPluginBase plugin) {
+ try {
+ // Lazy initialization of P2Index
+ if (p2Index == null) {
+ File indexCacheDir = new File(Platform.getStateLocation(PDECore.getDefault().getBundle()).toFile(),
+ "index"); //$NON-NLS-1$
+ p2Index = new P2Index(indexCacheDir);
+ }
+
+ String pluginId = plugin.getId();
+ String sourcePluginId = pluginId + ".source"; //$NON-NLS-1$
+
+ // Query the index for the source bundle using OSGi bundle capability
+ Map> repositories = p2Index
+ .lookupCapabilities(PublisherHelper.CAPABILITY_NS_OSGI_BUNDLE, sourcePluginId);
+
+ if (repositories != null && !repositories.isEmpty()) {
+ // Find the repository with the matching version
+ String pluginVersion = plugin.getVersion();
+ for (Entry> entry : repositories.entrySet()) {
+ for (Version version : entry.getValue()) {
+ if (version.toString().equals(pluginVersion)) {
+ // Found matching source bundle in the index
+ URI repositoryURI = URI.create(entry.getKey().getLocation().toString());
+ return downloadArtifact(repositoryURI, sourcePluginId, pluginVersion);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ // Log but don't fail - this is just one lookup strategy
+ PDECore.log(e);
+ }
+ return null;
+ }
+
+ /**
+ * Downloads an artifact from a P2 repository to the bundle pool.
+ *
+ * @param repositoryURL the repository URL
+ * @param artifactId the artifact ID (bundle symbolic name)
+ * @param version the artifact version
+ * @return the file location where it was downloaded or null if download failed
+ */
+ private IPath downloadArtifact(URI repositoryURL, String artifactId, String version) {
+ try {
+ IProgressMonitor monitor = new NullProgressMonitor();
+
+ // Get P2 managers
+ IMetadataRepositoryManager metadataManager = P2TargetUtils.getMetadataRepositoryManager();
+ IArtifactRepositoryManager artifactManager = P2TargetUtils.getArtifactRepositoryManager();
+
+ // Load the repository
+ IMetadataRepository metadataRepo = metadataManager.loadRepository(repositoryURL,
+ IRepository.REPOSITORY_HINT_MODIFIABLE, monitor);
+
+ // Find the installable unit for the source bundle
+ IQueryResult queryResult = metadataRepo.query(
+ QueryUtil.createIUQuery(artifactId, Version.create(version)), monitor);
+
+ if (queryResult.isEmpty()) {
+ PDECore.log("Source bundle " + artifactId + " version " + version + " not found in repository " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ + repositoryURL);
+ return null;
+ }
+
+ IInstallableUnit iu = queryResult.iterator().next();
+
+ // Get the artifact key
+ IArtifactKey artifactKey = iu.getArtifacts().iterator().next();
+
+ // Get the bundle pool (destination)
+ IArtifactRepository bundlePool = P2TargetUtils.getBundlePool();
+
+ // Check if already in bundle pool
+ if (bundlePool.contains(artifactKey)) {
+ // Already downloaded, find the file
+ File bundlePoolLocation = bundlePool.getLocation();
+ File artifactFile = new File(bundlePoolLocation,
+ "plugins/" + artifactId + "_" + version + ".jar"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (artifactFile.exists()) {
+ return new Path(artifactFile.getAbsolutePath());
+ }
+ }
+
+ // Download the artifact to the bundle pool
+ IArtifactRepository sourceRepo = artifactManager.loadRepository(repositoryURL,
+ IRepository.REPOSITORY_HINT_MODIFIABLE, monitor);
+
+ IArtifactRequest request = artifactManager.createMirrorRequest(artifactKey, bundlePool, null, null);
+ IStatus status = artifactManager.perform(new IArtifactRequest[] { request }, monitor);
+
+ if (status.isOK()) {
+ // Find the downloaded file in the bundle pool
+ File bundlePoolLocation = bundlePool.getLocation();
+ File artifactFile = new File(bundlePoolLocation,
+ "plugins/" + artifactId + "_" + version + ".jar"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (artifactFile.exists()) {
+ PDECore.log("Downloaded source bundle " + artifactId + " version " + version + " from " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ + repositoryURL);
+ return new Path(artifactFile.getAbsolutePath());
+ }
+ } else {
+ PDECore.log(status);
+ }
+
+ } catch (Exception e) {
+ PDECore.log(e);
+ }
+ return null;
+ }
+
+ /**
+ * Queries available software sites for the source bundle.
+ *
+ * @param plugin the plugin to locate sources for
+ * @return the path to the source bundle or null if not found
+ */
+ private IPath queryAvailableSoftwareSites(IPluginBase plugin) {
+ String pluginId = plugin.getId();
+ String sourcePluginId = pluginId + ".source"; //$NON-NLS-1$
+ String pluginVersion = plugin.getVersion();
+
+ try {
+ // Get the metadata repository manager
+ IMetadataRepositoryManager metadataManager = P2TargetUtils.getMetadataRepositoryManager();
+ if (metadataManager == null) {
+ return null;
+ }
+
+ // Get all known repositories from P2
+ URI[] knownRepositories = metadataManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
+ if (knownRepositories == null || knownRepositories.length == 0) {
+ return null;
+ }
+
+ // Loop through all known repositories
+ for (URI repositoryURI : knownRepositories) {
+ try {
+ // Try to download the source bundle from this repository
+ IPath result = downloadArtifact(repositoryURI, sourcePluginId, pluginVersion);
+ if (result != null) {
+ // Found and downloaded successfully
+ return result;
+ }
+ } catch (Exception e) {
+ // Log and continue to next repository
+ PDECore.log("Failed to search for source in known repository " + repositoryURI + ": " //$NON-NLS-1$ //$NON-NLS-2$
+ + e.getMessage());
+ }
+ }
+ } catch (Exception e) {
+ // Log but don't fail - this is just one lookup strategy
+ PDECore.log(e);
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the list of selected target platform names from preferences.
+ *
+ * @param store the preference store
+ * @return the list of selected target names
+ */
+ private List getSelectedTargets(IPreferenceStore store) {
+ String selectedTargets = store.getString(IPreferenceConstants.SOURCE_LOOKUP_SELECTED_TARGETS);
+ if (selectedTargets == null || selectedTargets.trim().isEmpty()) {
+ return List.of();
+ }
+ return Arrays.asList(selectedTargets.split(",")); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the list of configured repository URLs from preferences.
+ *
+ * @param store the preference store
+ * @return the list of repository URLs
+ */
+ private List getConfiguredRepositories(IPreferenceStore store) {
+ String repositories = store.getString(IPreferenceConstants.SOURCE_LOOKUP_REPOSITORIES);
+ if (repositories == null || repositories.trim().isEmpty()) {
+ return List.of();
+ }
+ return Arrays.asList(repositories.split(",")); //$NON-NLS-1$
+ }
+}
diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/copyfrom/oomph/P2Index.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/copyfrom/oomph/P2Index.java
new file mode 100644
index 00000000000..3644296e239
--- /dev/null
+++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/copyfrom/oomph/P2Index.java
@@ -0,0 +1,553 @@
+/*
+ * Copyright (c) 2014, 2016-2018 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.pde.internal.core.copyfrom.oomph;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl;
+import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectInputStream;
+import org.eclipse.equinox.p2.metadata.Version;
+
+/**
+ * @author Eike Stepper
+ */
+public class P2Index {
+
+ private static final String INDEX_BASE = "https://download.eclipse.org/oomph/index/"; //$NON-NLS-1$
+
+ private long timeStamp;
+
+ private Map repositories;
+
+ private Repository[] repositoriesArray;
+
+ private Map> capabilitiesMap;
+
+ private File repositoriesCacheFile;
+
+ private File capabilitiesCacheFile;
+
+ private int capabilitiesRefreshHours = -1;
+
+ private int repositoriesRefreshHours = -1;
+
+ private File basedir;
+
+ public P2Index(File basedir) {
+ this.basedir = basedir;
+ basedir.mkdirs();
+ }
+
+ private synchronized void initCapabilities() {
+ if (capabilitiesMap == null || capabilitiesCacheFile.lastModified()
+ + capabilitiesRefreshHours * 60 * 60 * 1000 < System.currentTimeMillis()) {
+ capabilitiesMap = new LinkedHashMap<>();
+
+ ZipFile zipFile = null;
+ InputStream inputStream = null;
+
+ try {
+ initCapabilitiesCacheFile();
+
+ zipFile = new ZipFile(capabilitiesCacheFile);
+ ZipEntry zipEntry = zipFile.getEntry("capabilities"); //$NON-NLS-1$
+
+ inputStream = zipFile.getInputStream(zipEntry);
+
+ Map
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/IPreferenceConstants.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/IPreferenceConstants.java
index b20fdcbe945..1ecf1a1b77e 100644
--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/IPreferenceConstants.java
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/IPreferenceConstants.java
@@ -66,4 +66,23 @@ public interface IPreferenceConstants extends ILaunchingPreferenceConstants {
*/
public static final String TEST_PLUGIN_PATTERN = "Preferences.MainPage.testPluginPattern";//$NON-NLS-1$
+ // Source Lookup preference page
+ /**
+ * Boolean preference whether additional source lookups are enabled
+ */
+ public static final String SOURCE_LOOKUP_ENABLED = "Preferences.SourceLookup.enabled"; //$NON-NLS-1$
+ /**
+ * String preference storing comma-separated ordered list of source lookup strategies
+ * Possible values: REPOSITORIES, TARGETS, INDEX, SITES
+ */
+ public static final String SOURCE_LOOKUP_ORDER = "Preferences.SourceLookup.order"; //$NON-NLS-1$
+ /**
+ * String preference storing comma-separated list of selected target platform names for source lookup
+ */
+ public static final String SOURCE_LOOKUP_SELECTED_TARGETS = "Preferences.SourceLookup.selectedTargets"; //$NON-NLS-1$
+ /**
+ * String preference storing comma-separated list of repository URLs for source lookup
+ */
+ public static final String SOURCE_LOOKUP_REPOSITORIES = "Preferences.SourceLookup.repositories"; //$NON-NLS-1$
+
}
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java
index 575ac6fd8fa..57f07b74aaa 100644
--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java
@@ -3444,4 +3444,22 @@ public class PDEUIMessages extends NLS {
public static String AddMatchingVersion_RequireBundle;
+ public static String SourceLookupPreferencePage_description;
+ public static String SourceLookupPreferencePage_enableSourceLookup;
+ public static String SourceLookupPreferencePage_orderGroup;
+ public static String SourceLookupPreferencePage_orderDescription;
+ public static String SourceLookupPreferencePage_up;
+ public static String SourceLookupPreferencePage_down;
+ public static String SourceLookupPreferencePage_targetsGroup;
+ public static String SourceLookupPreferencePage_repositoriesGroup;
+ public static String SourceLookupPreferencePage_addRepository;
+ public static String SourceLookupPreferencePage_removeRepository;
+ public static String SourceLookupPreferencePage_addRepositoryTitle;
+ public static String SourceLookupPreferencePage_addRepositoryMessage;
+ public static String SourceLookupPreferencePage_unnamedTarget;
+ public static String SourceLookupPreferencePage_strategy_REPOSITORIES;
+ public static String SourceLookupPreferencePage_strategy_TARGETS;
+ public static String SourceLookupPreferencePage_strategy_INDEX;
+ public static String SourceLookupPreferencePage_strategy_SITES;
+
}
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties
index 8b45f594b30..d4d284e9ade 100644
--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties
@@ -2728,4 +2728,22 @@ ProjectUpdateChange_configure_nature_and_builder=Update natures and builder
ProjectUpdateChange_convert_manifest_to_bnd=Convert MANIFEST.MF to bnd instructions
ProjectUpdateChange_convert_build_to_bnd=Convert build.properties to bnd instructions
ProjectUpdateChange_set_pde_preference=Set {0} in preferences
-StatePage_title=Target State
\ No newline at end of file
+StatePage_title=Target State
+# Source Lookup Preference Page
+SourceLookupPreferencePage_description=Configure source lookup settings for resolving source code
+SourceLookupPreferencePage_enableSourceLookup=Enable additional source lookups
+SourceLookupPreferencePage_orderGroup=Source Lookup Order
+SourceLookupPreferencePage_orderDescription=Configure the order in which source lookups are performed (top to bottom):
+SourceLookupPreferencePage_up=Up
+SourceLookupPreferencePage_down=Down
+SourceLookupPreferencePage_targetsGroup=Search in locations of the selected Targets
+SourceLookupPreferencePage_repositoriesGroup=Search in these repositories
+SourceLookupPreferencePage_addRepository=Add...
+SourceLookupPreferencePage_removeRepository=Remove
+SourceLookupPreferencePage_addRepositoryTitle=Add Repository
+SourceLookupPreferencePage_addRepositoryMessage=Enter repository URL:
+SourceLookupPreferencePage_unnamedTarget=
+SourceLookupPreferencePage_strategy_REPOSITORIES=Configured Repositories
+SourceLookupPreferencePage_strategy_TARGETS=Selected Target Platforms
+SourceLookupPreferencePage_strategy_INDEX=Eclipse Index
+SourceLookupPreferencePage_strategy_SITES=Available Software Sites
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/preferences/PreferenceInitializer.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/preferences/PreferenceInitializer.java
index 28a89439567..6d5df6aae92 100644
--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/preferences/PreferenceInitializer.java
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/preferences/PreferenceInitializer.java
@@ -32,6 +32,13 @@ public void initializeDefaultPreferences() {
store.setDefault(IPreferenceConstants.WORKSPACE_PLUGINS_OVERRIDE_TARGET, true);
store.setDefault(IPreferenceConstants.DISABLE_API_ANALYSIS_BUILDER, false);
store.setDefault(IPreferenceConstants.TEST_PLUGIN_PATTERN, ICoreConstants.TEST_PLUGIN_PATTERN_DEFAULTVALUE);
+
+ // Source Lookup defaults
+ store.setDefault(IPreferenceConstants.SOURCE_LOOKUP_ENABLED, false);
+ // Default order: configured repositories, selected target, eclipse index, available software sites
+ store.setDefault(IPreferenceConstants.SOURCE_LOOKUP_ORDER, "REPOSITORIES,TARGETS,INDEX,SITES"); //$NON-NLS-1$
+ store.setDefault(IPreferenceConstants.SOURCE_LOOKUP_SELECTED_TARGETS, ""); //$NON-NLS-1$
+ store.setDefault(IPreferenceConstants.SOURCE_LOOKUP_REPOSITORIES, ""); //$NON-NLS-1$
}
}
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/preferences/SourceLookupPreferencePage.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/preferences/SourceLookupPreferencePage.java
new file mode 100644
index 00000000000..ee2464354e9
--- /dev/null
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/preferences/SourceLookupPreferencePage.java
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ * Copyright (c) 2025 Christoph Läubrich and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Christoph Läubrich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.internal.ui.preferences;
+
+import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.pde.core.target.ITargetDefinition;
+import org.eclipse.pde.core.target.ITargetHandle;
+import org.eclipse.pde.core.target.ITargetPlatformService;
+import org.eclipse.pde.internal.core.target.TargetPlatformService;
+import org.eclipse.pde.internal.ui.IHelpContextIds;
+import org.eclipse.pde.internal.ui.IPreferenceConstants;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.pde.internal.ui.SWTFactory;
+import org.eclipse.swt.SWT;
+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.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Preference page for managing source lookup settings
+ */
+public class SourceLookupPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+ public static final String ID = "org.eclipse.pde.ui.SourceLookupPreferencePage"; //$NON-NLS-1$
+
+ // Source lookup strategy identifiers
+ private static final String STRATEGY_REPOSITORIES = "REPOSITORIES"; //$NON-NLS-1$
+ private static final String STRATEGY_TARGETS = "TARGETS"; //$NON-NLS-1$
+ private static final String STRATEGY_INDEX = "INDEX"; //$NON-NLS-1$
+ private static final String STRATEGY_SITES = "SITES"; //$NON-NLS-1$
+
+ private Button fEnableSourceLookup;
+ private TableViewer fOrderTableViewer;
+ private Button fUpButton;
+ private Button fDownButton;
+ private CheckboxTableViewer fTargetsTableViewer;
+ private CheckboxTableViewer fRepositoriesTableViewer;
+ private Button fAddRepositoryButton;
+ private Button fRemoveRepositoryButton;
+
+ private List fLookupOrder = new ArrayList<>();
+ private List fTargets = new ArrayList<>();
+ private List fRepositories = new ArrayList<>();
+
+ public SourceLookupPreferencePage() {
+ setPreferenceStore(PDEPlugin.getDefault().getPreferenceStore());
+ setDescription(PDEUIMessages.SourceLookupPreferencePage_description);
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Composite composite = SWTFactory.createComposite(parent, 1, 1, GridData.FILL_BOTH, 0, 0);
+ ((GridLayout) composite.getLayout()).verticalSpacing = 15;
+ ((GridLayout) composite.getLayout()).marginTop = 15;
+
+ // Enable checkbox
+ fEnableSourceLookup = new Button(composite, SWT.CHECK);
+ fEnableSourceLookup.setText(PDEUIMessages.SourceLookupPreferencePage_enableSourceLookup);
+ fEnableSourceLookup.setSelection(getPreferenceStore().getBoolean(IPreferenceConstants.SOURCE_LOOKUP_ENABLED));
+ fEnableSourceLookup.addSelectionListener(widgetSelectedAdapter(e -> updateEnablement()));
+
+ // Lookup order group
+ Group orderGroup = SWTFactory.createGroup(composite, PDEUIMessages.SourceLookupPreferencePage_orderGroup, 2, 1, GridData.FILL_HORIZONTAL);
+
+ Label orderDescription = new Label(orderGroup, SWT.WRAP);
+ orderDescription.setText(PDEUIMessages.SourceLookupPreferencePage_orderDescription);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ gd.widthHint = 400;
+ orderDescription.setLayoutData(gd);
+
+ fOrderTableViewer = new TableViewer(orderGroup, SWT.BORDER | SWT.V_SCROLL);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = 100;
+ fOrderTableViewer.getControl().setLayoutData(gd);
+ fOrderTableViewer.setLabelProvider(new LabelProvider() {
+ @Override
+ public String getText(Object element) {
+ return getStrategyLabel((String) element);
+ }
+ });
+ fOrderTableViewer.setContentProvider(ArrayContentProvider.getInstance());
+ fOrderTableViewer.addSelectionChangedListener(event -> updateOrderButtons());
+
+ // Up/Down buttons
+ Composite buttonComposite = SWTFactory.createComposite(orderGroup, 1, 1, GridData.FILL_VERTICAL | GridData.VERTICAL_ALIGN_BEGINNING, 0, 0);
+
+ fUpButton = SWTFactory.createPushButton(buttonComposite, PDEUIMessages.SourceLookupPreferencePage_up, null);
+ fUpButton.addSelectionListener(widgetSelectedAdapter(e -> handleMoveUp()));
+
+ fDownButton = SWTFactory.createPushButton(buttonComposite, PDEUIMessages.SourceLookupPreferencePage_down, null);
+ fDownButton.addSelectionListener(widgetSelectedAdapter(e -> handleMoveDown()));
+
+ // Load lookup order
+ loadLookupOrder();
+
+ // Target platforms group
+ Group targetsGroup = SWTFactory.createGroup(composite, PDEUIMessages.SourceLookupPreferencePage_targetsGroup, 1, 1, GridData.FILL_BOTH);
+ targetsGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ fTargetsTableViewer = CheckboxTableViewer.newCheckList(targetsGroup, SWT.BORDER | SWT.V_SCROLL);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = 120;
+ fTargetsTableViewer.getControl().setLayoutData(gd);
+ fTargetsTableViewer.setLabelProvider(new LabelProvider() {
+ @Override
+ public String getText(Object element) {
+ if (element instanceof ITargetDefinition) {
+ String name = ((ITargetDefinition) element).getName();
+ return name != null ? name : PDEUIMessages.SourceLookupPreferencePage_unnamedTarget;
+ }
+ return super.getText(element);
+ }
+ });
+ fTargetsTableViewer.setContentProvider(ArrayContentProvider.getInstance());
+
+ // Load available targets
+ loadTargets();
+
+ // Repositories group
+ Group repositoriesGroup = SWTFactory.createGroup(composite, PDEUIMessages.SourceLookupPreferencePage_repositoriesGroup, 2, 1, GridData.FILL_BOTH);
+ repositoriesGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ fRepositoriesTableViewer = CheckboxTableViewer.newCheckList(repositoriesGroup, SWT.BORDER | SWT.V_SCROLL);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = 120;
+ fRepositoriesTableViewer.getControl().setLayoutData(gd);
+ fRepositoriesTableViewer.setLabelProvider(new LabelProvider());
+ fRepositoriesTableViewer.setContentProvider(ArrayContentProvider.getInstance());
+ fRepositoriesTableViewer.addSelectionChangedListener(event -> updateRepositoryButtons());
+
+ // Load repositories
+ loadRepositories();
+
+ // Repository buttons
+ buttonComposite = SWTFactory.createComposite(repositoriesGroup, 1, 1, GridData.FILL_VERTICAL | GridData.VERTICAL_ALIGN_BEGINNING, 0, 0);
+
+ fAddRepositoryButton = SWTFactory.createPushButton(buttonComposite, PDEUIMessages.SourceLookupPreferencePage_addRepository, null);
+ fAddRepositoryButton.addSelectionListener(widgetSelectedAdapter(e -> handleAddRepository()));
+
+ fRemoveRepositoryButton = SWTFactory.createPushButton(buttonComposite, PDEUIMessages.SourceLookupPreferencePage_removeRepository, null);
+ fRemoveRepositoryButton.addSelectionListener(widgetSelectedAdapter(e -> handleRemoveRepository()));
+
+ updateEnablement();
+ updateRepositoryButtons();
+ updateOrderButtons();
+
+ return composite;
+ }
+
+ private String getStrategyLabel(String strategy) {
+ switch (strategy) {
+ case STRATEGY_REPOSITORIES:
+ return PDEUIMessages.SourceLookupPreferencePage_strategy_REPOSITORIES;
+ case STRATEGY_TARGETS:
+ return PDEUIMessages.SourceLookupPreferencePage_strategy_TARGETS;
+ case STRATEGY_INDEX:
+ return PDEUIMessages.SourceLookupPreferencePage_strategy_INDEX;
+ case STRATEGY_SITES:
+ return PDEUIMessages.SourceLookupPreferencePage_strategy_SITES;
+ default:
+ return strategy;
+ }
+ }
+
+ private void loadLookupOrder() {
+ String order = getPreferenceStore().getString(IPreferenceConstants.SOURCE_LOOKUP_ORDER);
+ if (order == null || order.trim().isEmpty()) {
+ // Use default order
+ fLookupOrder = new ArrayList<>(Arrays.asList(STRATEGY_REPOSITORIES, STRATEGY_TARGETS, STRATEGY_INDEX, STRATEGY_SITES));
+ } else {
+ fLookupOrder = new ArrayList<>(Arrays.asList(order.split(","))); //$NON-NLS-1$
+ }
+ fOrderTableViewer.setInput(fLookupOrder);
+ }
+
+ private void loadTargets() {
+ ITargetPlatformService service = TargetPlatformService.getDefault();
+ if (service != null) {
+ ITargetHandle[] targets = service.getTargets(null);
+ for (ITargetHandle target : targets) {
+ try {
+ fTargets.add(target.getTargetDefinition());
+ } catch (CoreException e) {
+ PDEPlugin.log(e);
+ }
+ }
+ fTargetsTableViewer.setInput(fTargets);
+
+ // Restore selected targets
+ String selectedTargets = getPreferenceStore().getString(IPreferenceConstants.SOURCE_LOOKUP_SELECTED_TARGETS);
+ if (!selectedTargets.isEmpty()) {
+ List selectedNames = Arrays.asList(selectedTargets.split(",")); //$NON-NLS-1$
+ List toCheck = fTargets.stream()
+ .filter(t -> t.getName() != null && selectedNames.contains(t.getName()))
+ .collect(Collectors.toList());
+ fTargetsTableViewer.setCheckedElements(toCheck.toArray());
+ }
+ }
+ }
+
+ private void loadRepositories() {
+ String repositories = getPreferenceStore().getString(IPreferenceConstants.SOURCE_LOOKUP_REPOSITORIES);
+ if (!repositories.isEmpty()) {
+ fRepositories = new ArrayList<>(Arrays.asList(repositories.split(","))); //$NON-NLS-1$
+ fRepositoriesTableViewer.setInput(fRepositories);
+ fRepositoriesTableViewer.setAllChecked(true);
+ }
+ }
+
+ private void handleMoveUp() {
+ IStructuredSelection selection = (IStructuredSelection) fOrderTableViewer.getSelection();
+ if (!selection.isEmpty()) {
+ String strategy = (String) selection.getFirstElement();
+ int index = fLookupOrder.indexOf(strategy);
+ if (index > 0) {
+ fLookupOrder.remove(index);
+ fLookupOrder.add(index - 1, strategy);
+ fOrderTableViewer.refresh();
+ fOrderTableViewer.setSelection(selection);
+ updateOrderButtons();
+ }
+ }
+ }
+
+ private void handleMoveDown() {
+ IStructuredSelection selection = (IStructuredSelection) fOrderTableViewer.getSelection();
+ if (!selection.isEmpty()) {
+ String strategy = (String) selection.getFirstElement();
+ int index = fLookupOrder.indexOf(strategy);
+ if (index < fLookupOrder.size() - 1) {
+ fLookupOrder.remove(index);
+ fLookupOrder.add(index + 1, strategy);
+ fOrderTableViewer.refresh();
+ fOrderTableViewer.setSelection(selection);
+ updateOrderButtons();
+ }
+ }
+ }
+
+ private void handleAddRepository() {
+ InputDialog dialog = new InputDialog(getShell(),
+ PDEUIMessages.SourceLookupPreferencePage_addRepositoryTitle,
+ PDEUIMessages.SourceLookupPreferencePage_addRepositoryMessage,
+ "", //$NON-NLS-1$
+ null);
+ if (dialog.open() == Window.OK) {
+ String url = dialog.getValue().trim();
+ if (!url.isEmpty() && !fRepositories.contains(url)) {
+ fRepositories.add(url);
+ fRepositoriesTableViewer.setInput(fRepositories);
+ fRepositoriesTableViewer.setChecked(url, true);
+ }
+ }
+ }
+
+ private void handleRemoveRepository() {
+ IStructuredSelection selection = (IStructuredSelection) fRepositoriesTableViewer.getSelection();
+ if (!selection.isEmpty()) {
+ Object[] elements = selection.toArray();
+ for (Object element : elements) {
+ fRepositories.remove(element);
+ }
+ fRepositoriesTableViewer.setInput(fRepositories);
+ }
+ }
+
+ private void updateEnablement() {
+ boolean enabled = fEnableSourceLookup.getSelection();
+ fOrderTableViewer.getControl().setEnabled(enabled);
+ fUpButton.setEnabled(enabled);
+ fDownButton.setEnabled(enabled);
+ fTargetsTableViewer.getControl().setEnabled(enabled);
+ fRepositoriesTableViewer.getControl().setEnabled(enabled);
+ fAddRepositoryButton.setEnabled(enabled);
+ fRemoveRepositoryButton.setEnabled(enabled && !fRepositoriesTableViewer.getSelection().isEmpty());
+ updateOrderButtons();
+ }
+
+ private void updateOrderButtons() {
+ if (!fEnableSourceLookup.getSelection()) {
+ fUpButton.setEnabled(false);
+ fDownButton.setEnabled(false);
+ return;
+ }
+
+ IStructuredSelection selection = (IStructuredSelection) fOrderTableViewer.getSelection();
+ if (selection.isEmpty()) {
+ fUpButton.setEnabled(false);
+ fDownButton.setEnabled(false);
+ } else {
+ String strategy = (String) selection.getFirstElement();
+ int index = fLookupOrder.indexOf(strategy);
+ fUpButton.setEnabled(index > 0);
+ fDownButton.setEnabled(index < fLookupOrder.size() - 1);
+ }
+ }
+
+ private void updateRepositoryButtons() {
+ fRemoveRepositoryButton.setEnabled(fEnableSourceLookup.getSelection() && !fRepositoriesTableViewer.getSelection().isEmpty());
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ Dialog.applyDialogFont(getControl());
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IHelpContextIds.MAIN_PREFERENCE_PAGE);
+ }
+
+ @Override
+ public boolean performOk() {
+ getPreferenceStore().setValue(IPreferenceConstants.SOURCE_LOOKUP_ENABLED, fEnableSourceLookup.getSelection());
+
+ // Save lookup order
+ String order = String.join(",", fLookupOrder); //$NON-NLS-1$
+ getPreferenceStore().setValue(IPreferenceConstants.SOURCE_LOOKUP_ORDER, order);
+
+ // Save selected targets
+ Object[] checkedTargets = fTargetsTableViewer.getCheckedElements();
+ String selectedTargets = Arrays.stream(checkedTargets)
+ .filter(t -> t instanceof ITargetDefinition)
+ .map(t -> ((ITargetDefinition) t).getName())
+ .filter(name -> name != null)
+ .collect(Collectors.joining(",")); //$NON-NLS-1$
+ getPreferenceStore().setValue(IPreferenceConstants.SOURCE_LOOKUP_SELECTED_TARGETS, selectedTargets);
+
+ // Save repositories
+ String repositories = String.join(",", fRepositories); //$NON-NLS-1$
+ getPreferenceStore().setValue(IPreferenceConstants.SOURCE_LOOKUP_REPOSITORIES, repositories);
+
+ return super.performOk();
+ }
+
+ @Override
+ protected void performDefaults() {
+ fEnableSourceLookup.setSelection(getPreferenceStore().getDefaultBoolean(IPreferenceConstants.SOURCE_LOOKUP_ENABLED));
+
+ // Reset to default order
+ fLookupOrder = new ArrayList<>(Arrays.asList(STRATEGY_REPOSITORIES, STRATEGY_TARGETS, STRATEGY_INDEX, STRATEGY_SITES));
+ fOrderTableViewer.setInput(fLookupOrder);
+ fOrderTableViewer.refresh();
+
+ fTargetsTableViewer.setCheckedElements(new Object[0]);
+ fRepositories.clear();
+ fRepositoriesTableViewer.setInput(fRepositories);
+ updateEnablement();
+ updateRepositoryButtons();
+ updateOrderButtons();
+ super.performDefaults();
+ }
+
+ @Override
+ public void init(IWorkbench workbench) {
+ }
+}