From 3f4449d92ca02be8e4fdb268634c37b6557251cb Mon Sep 17 00:00:00 2001 From: Lars Vogel Date: Tue, 4 Aug 2026 19:02:06 +0200 Subject: [PATCH 1/2] Allow rewriting image URLs via an IImageURLModifier strategy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Icon packs and RCP applications cannot substitute platform icons except through the Equinox transforms hook, which needs a framework extension enabled on the command line. URLImageDescriptor now asks an IImageURLModifier for the URL to load. The workbench installs the highest ranked OSGi service of that type, so an icon pack needs no startup code; RCP applications can call ImageDescriptor.setURLModifier instead. HiDPI variants are derived from the rewritten URL. Images are not reloaded, so a new icon pack takes effect after a restart. The API is marked experimental. Assisted-by: multiple AI agents and layers of automated tooling 🤖 --- .../META-INF/MANIFEST.MF | 2 +- .../swt/ImageURLModifierTracker.java | 64 ++++++++++ .../workbench/swt/WorkbenchSWTActivator.java | 8 ++ .../jface/resource/IImageURLModifier.java | 41 ++++++ .../jface/resource/ImageDescriptor.java | 18 +++ .../jface/resource/URLImageDescriptor.java | 33 +++-- .../org/eclipse/e4/ui/tests/UIAllTests.java | 2 + .../ImageURLModifierTrackerTest.java | 119 ++++++++++++++++++ .../tests/images/UrlImageDescriptorTest.java | 114 ++++++++++++++++- 9 files changed, 391 insertions(+), 10 deletions(-) create mode 100644 bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ImageURLModifierTracker.java create mode 100644 bundles/org.eclipse.jface/src/org/eclipse/jface/resource/IImageURLModifier.java create mode 100644 tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ImageURLModifierTrackerTest.java diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/MANIFEST.MF index fc7c8b7746f..c21c53df8ad 100644 --- a/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/MANIFEST.MF @@ -9,7 +9,7 @@ Bundle-Activator: org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator Require-Bundle: org.eclipse.e4.ui.workbench;bundle-version="0.10.0", org.eclipse.e4.core.services;bundle-version="1.0.0", org.eclipse.e4.ui.services;bundle-version="0.1.0", - org.eclipse.jface;bundle-version="[3.39.0,4.0.0)", + org.eclipse.jface;bundle-version="[3.41.0,4.0.0)", org.eclipse.e4.ui.dialogs;bundle-version="1.1.600", org.eclipse.core.databinding;bundle-version="[1.2.0,2.0.0)", org.eclipse.jface.databinding;bundle-version="[1.3.0,2.0.0)", diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ImageURLModifierTracker.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ImageURLModifierTracker.java new file mode 100644 index 00000000000..5c21fa85225 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ImageURLModifierTracker.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2026 vogella GmbH 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: + * Lars Vogel - initial API and implementation + *******************************************************************************/ +package org.eclipse.e4.ui.internal.workbench.swt; + +import org.eclipse.jface.resource.IImageURLModifier; +import org.eclipse.jface.resource.ImageDescriptor; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; + +/** + * Installs the highest ranked {@link IImageURLModifier} service in JFace. + * Tracked because the contributing bundle may start after the workbench. + */ +class ImageURLModifierTracker extends ServiceTracker { + + private ServiceReference installed; + + ImageURLModifierTracker(BundleContext context) { + super(context, IImageURLModifier.class, null); + } + + @Override + public synchronized IImageURLModifier addingService(ServiceReference reference) { + IImageURLModifier modifier = super.addingService(reference); + // not tracked until this returns, so it cannot be picked by installBest() + if (modifier != null && (installed == null || reference.compareTo(installed) > 0)) { + installed = reference; + ImageDescriptor.setURLModifier(modifier); + } + return modifier; + } + + @Override + public synchronized void modifiedService(ServiceReference reference, + IImageURLModifier service) { + installBest(); + } + + @Override + public synchronized void removedService(ServiceReference reference, + IImageURLModifier service) { + super.removedService(reference, service); + if (reference.equals(installed)) { + installBest(); + } + } + + private void installBest() { + installed = getServiceReference(); + ImageDescriptor.setURLModifier(installed == null ? null : getService(installed)); + } +} diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchSWTActivator.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchSWTActivator.java index 3a7f5a5cad2..3efea7fc8b1 100644 --- a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchSWTActivator.java +++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchSWTActivator.java @@ -43,6 +43,7 @@ import org.eclipse.core.runtime.Platform; import org.eclipse.jface.dialogs.DialogSettings; import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.resource.IImageURLModifier; import org.eclipse.osgi.service.datalocation.Location; import org.eclipse.osgi.service.debug.DebugOptions; import org.eclipse.osgi.service.debug.DebugOptionsListener; @@ -62,6 +63,7 @@ public class WorkbenchSWTActivator implements BundleActivator, DebugOptionsListe private BundleContext context; private ServiceTracker locationTracker; + private ServiceTracker imageURLModifierTracker; private static WorkbenchSWTActivator activator; private DebugTrace trace; @@ -89,11 +91,17 @@ public void start(BundleContext context) throws Exception { Hashtable props = new Hashtable<>(2); props.put(DebugOptions.LISTENER_SYMBOLICNAME, PI_RENDERERS); context.registerService(DebugOptionsListener.class, this, props); + imageURLModifierTracker = new ImageURLModifierTracker(context); + imageURLModifierTracker.open(); } @Override public void stop(BundleContext context) throws Exception { saveDialogSettings(); + if (imageURLModifierTracker != null) { + imageURLModifierTracker.close(); + imageURLModifierTracker = null; + } } public Bundle getBundle() { diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/IImageURLModifier.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/IImageURLModifier.java new file mode 100644 index 00000000000..5dfb2182ec1 --- /dev/null +++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/IImageURLModifier.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2026 vogella GmbH 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: + * Lars Vogel - initial API and implementation + *******************************************************************************/ +package org.eclipse.jface.resource; + +import java.net.URL; + +/** + * Rewrites image URLs before they are loaded, so icons can be substituted + * without changing the code that creates the image descriptors. The E4 + * workbench installs the highest ranked OSGi service of this type. + *

+ * EXPERIMENTAL. This interface has been added as part of a + * work in progress. There is no guarantee that this API will remain the same. + *

+ * + * @see ImageDescriptor#setURLModifier(IImageURLModifier) + * @since 3.41 + */ +@FunctionalInterface +public interface IImageURLModifier { + + /** + * Returns the URL to load instead of the given one, or null to + * keep it. Called for every image load, so it must be fast and thread-safe. + * + * @param originalURL the URL the image would be loaded from + * @return the replacement URL, or null to keep the original + */ + URL modifyURL(URL originalURL); +} diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/ImageDescriptor.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/ImageDescriptor.java index 231f9b71db5..757f25de501 100644 --- a/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/ImageDescriptor.java +++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/ImageDescriptor.java @@ -82,6 +82,24 @@ protected ImageDescriptor() { super(shouldBeCached); } + /** Set from OSGi service events, read from any thread. */ + static volatile IImageURLModifier urlModifier; + + /** + * Installs the modifier consulted when an image is loaded from a URL. Images + * created before are not reloaded. + *

+ * EXPERIMENTAL. This method has been added as part of a work + * in progress. There is no guarantee that this API will remain the same. + *

+ * + * @param modifier the modifier, or null to remove it + * @since 3.41 + */ + public static void setURLModifier(IImageURLModifier modifier) { + urlModifier = modifier; + } + private static final ImageDescriptor NULL_IMAGE = createFromImageDataProvider(z -> null); /** diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/URLImageDescriptor.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/URLImageDescriptor.java index 646ca5cb90f..0f306a7913f 100644 --- a/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/URLImageDescriptor.java +++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/URLImageDescriptor.java @@ -63,7 +63,7 @@ private ImageFileNameProvider createURLImageFileNameProvider() { // The calling image will do that itself! return getFilePath(tempURL, logIOException); } - return getZoomedImageSource(tempURL, url, zoom, u -> getFilePath(u, logIOException)); + return getZoomedImageSource(tempURL, zoom, u -> getFilePath(u, logIOException)); } return null; }; @@ -107,12 +107,12 @@ public ImageData getImageData(int zoom) { if (zoom == 100 || canLoadAtZoom(tempURL, zoom)) { return getImageData(tempURL, 100, zoom); } - return getZoomedImageSource(tempURL, url, zoom, u -> getImageData(u, zoom, zoom)); + return getZoomedImageSource(tempURL, zoom, u -> getImageData(u, zoom, zoom)); } return null; } - private static R getZoomedImageSource(URL url, String urlString, int zoom, Function getImage) { + private static R getZoomedImageSource(URL url, int zoom, Function getImage) { URL xUrl = getxURL(url, zoom); if (xUrl != null) { R xdata = getImage.apply(xUrl); @@ -120,9 +120,10 @@ private static R getZoomedImageSource(URL url, String urlString, int zoom, F return xdata; } } - String xpath = getxPath(urlString, zoom); + // derived from the already modified URL, so the modifier must not run again + String xpath = getxPath(url.toExternalForm(), zoom); if (xpath != null) { - URL xPathUrl = getURL(xpath); + URL xPathUrl = toURL(xpath); if (xPathUrl != null) { return getImage.apply(xPathUrl); } @@ -352,14 +353,30 @@ public Image createImage(boolean returnMissingImageOnError, Device device) { } } + /** + * Resolves the given URL string, applying the URL modifier. Every code path of + * this descriptor resolves its URL here. + */ private static URL getURL(String urlString) { - URL result = null; + URL result = toURL(urlString); + IImageURLModifier modifier = urlModifier; + if (result != null && modifier != null) { + URL modified = modifier.modifyURL(result); + if (modified != null) { + result = modified; + } + } + return result; + } + + @SuppressWarnings("deprecation") // keeps the lenient parsing of new URL(String) + private static URL toURL(String urlString) { try { - result = new URL(urlString); + return new URL(urlString); } catch (MalformedURLException e) { Policy.logException(e); + return null; } - return result; } @Override diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java index f77ed00292a..9a9ef8c92ac 100644 --- a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java +++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java @@ -33,6 +33,7 @@ import org.eclipse.e4.ui.tests.workbench.ExtensionsSortTests; import org.eclipse.e4.ui.tests.workbench.HandlerActivationTest; import org.eclipse.e4.ui.tests.workbench.HandlerTest; +import org.eclipse.e4.ui.tests.workbench.ImageURLModifierTrackerTest; import org.eclipse.e4.ui.tests.workbench.InjectionEventTest; import org.eclipse.e4.ui.tests.workbench.MApplicationCommandAccessTest; import org.eclipse.e4.ui.tests.workbench.MMenuItemTest; @@ -101,6 +102,7 @@ ExtensionsSortTests.class, HandlerActivationTest.class, ModelAssemblerTests.class, + ImageURLModifierTrackerTest.class, ModelAssemblerFragmentOrderingTests.class, E4ResourceTest.class, AreaRendererTest.class, diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ImageURLModifierTrackerTest.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ImageURLModifierTrackerTest.java new file mode 100644 index 00000000000..2bbcb3f3886 --- /dev/null +++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ImageURLModifierTrackerTest.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2026 vogella GmbH 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: + * Lars Vogel - initial API and implementation + *******************************************************************************/ +package org.eclipse.e4.ui.tests.workbench; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.Adapters; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.resource.IImageURLModifier; +import org.eclipse.jface.resource.ImageDescriptor; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceRegistration; + +/** + * Tests that the E4 workbench installs the highest ranked + * {@link IImageURLModifier} service in JFace. + */ +public class ImageURLModifierTrackerTest { + + private final BundleContext context = FrameworkUtil.getBundle(ImageURLModifierTrackerTest.class) + .getBundleContext(); + private final List> registrations = new ArrayList<>(); + private ImageDescriptor descriptor; + + @BeforeAll + public static void startWorkbenchBundle() throws Exception { + // lazily activated, and earlier tests may not have loaded its classes + Platform.getBundle("org.eclipse.e4.ui.workbench.swt").start(Bundle.START_TRANSIENT); + } + + @BeforeEach + public void setUp() throws Exception { + descriptor = ImageDescriptor.createFromURL(URI.create("file:/original.png").toURL()); + } + + @AfterEach + public void tearDown() { + for (ServiceRegistration registration : registrations) { + try { + registration.unregister(); + } catch (IllegalStateException e) { + // already unregistered by the test + } + } + } + + @Test + public void testHighestRankedModifierIsInstalled() { + register("a", 1); + register("b", 5); + register("c", 3); + + assertEquals("file:/b.png", resolvedURL()); + } + + @Test + public void testRemovingInstalledModifierFallsBackToNext() { + register("a", 1); + ServiceRegistration b = register("b", 5); + + b.unregister(); + assertEquals("file:/a.png", resolvedURL()); + + registrations.get(0).unregister(); + assertEquals("file:/original.png", resolvedURL()); + } + + @Test + public void testRankingChangeIsApplied() { + ServiceRegistration a = register("a", 1); + register("b", 5); + + a.setProperties(FrameworkUtil.asDictionary(Map.of(Constants.SERVICE_RANKING, 10))); + + assertEquals("file:/a.png", resolvedURL()); + } + + private ServiceRegistration register(String name, int ranking) { + IImageURLModifier modifier = _ -> { + try { + return URI.create("file:/" + name + ".png").toURL(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + }; + ServiceRegistration registration = context.registerService(IImageURLModifier.class, + modifier, FrameworkUtil.asDictionary(Map.of(Constants.SERVICE_RANKING, ranking))); + registrations.add(registration); + return registration; + } + + private String resolvedURL() { + return Adapters.adapt(descriptor, URL.class).toExternalForm(); + } +} diff --git a/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/images/UrlImageDescriptorTest.java b/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/images/UrlImageDescriptorTest.java index 31ef2696927..ad88d6ac8e0 100644 --- a/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/images/UrlImageDescriptorTest.java +++ b/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/images/UrlImageDescriptorTest.java @@ -33,6 +33,7 @@ import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.ImageFileNameProvider; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -202,4 +203,115 @@ public void testAdaptToURL() { assertEquals(imageDataOrig200.height, imageDataURL200.height); } -} \ No newline at end of file + @AfterEach + public void clearURLModifier() { + ImageDescriptor.setURLModifier(null); + } + + @Test + public void testNoURLModifierInstalledByDefault() { + ImageDescriptor descriptor = ImageDescriptor + .createFromURL(FileImageDescriptorTest.class.getResource("/icons/imagetests/zoomIn.png")); + assertEquals("zoomIn.png", IPath.fromOSString(imagePath(descriptor, 100)).lastSegment()); + } + + @Test + public void testURLModifierRedirectsImageData() { + URL zoomIn = FileImageDescriptorTest.class.getResource("/icons/imagetests/zoomIn.png"); + URL rectangular = FileImageDescriptorTest.class.getResource("/icons/imagetests/rectangular-57x16.png"); + ImageData original = ImageDescriptor.createFromURL(zoomIn).getImageData(100); + ImageData replacement = ImageDescriptor.createFromURL(rectangular).getImageData(100); + assertNotEquals(original.width, replacement.width, "test images are indistinguishable"); + + ImageDescriptor descriptor = ImageDescriptor.createFromURL(zoomIn); + ImageDescriptor.setURLModifier(url -> zoomIn.toExternalForm().equals(url.toExternalForm()) ? rectangular : url); + + assertEquals(replacement.width, descriptor.getImageData(100).width); + } + + @Test + public void testURLModifierLeavesUnmatchedURLsAlone() { + ImageDescriptor descriptor = ImageDescriptor + .createFromURL(FileImageDescriptorTest.class.getResource("/icons/imagetests/zoomIn.png")); + ImageDescriptor.setURLModifier(url -> url); + + assertEquals("zoomIn.png", IPath.fromOSString(imagePath(descriptor, 100)).lastSegment()); + } + + @Test + public void testURLModifierReturningNullKeepsOriginalURL() { + ImageDescriptor descriptor = ImageDescriptor + .createFromURL(FileImageDescriptorTest.class.getResource("/icons/imagetests/zoomIn.png")); + ImageDescriptor.setURLModifier(_ -> null); + + assertEquals("zoomIn.png", IPath.fromOSString(imagePath(descriptor, 100)).lastSegment()); + } + + @Test + public void testURLModifierIsClearedByNull() { + URL zoomIn = FileImageDescriptorTest.class.getResource("/icons/imagetests/zoomIn.png"); + URL rectangular = FileImageDescriptorTest.class.getResource("/icons/imagetests/rectangular-57x16.png"); + ImageDescriptor descriptor = ImageDescriptor.createFromURL(zoomIn); + + ImageDescriptor.setURLModifier(_ -> rectangular); + assertEquals("rectangular-57x16.png", IPath.fromOSString(imagePath(descriptor, 100)).lastSegment()); + + ImageDescriptor.setURLModifier(null); + assertEquals("zoomIn.png", IPath.fromOSString(imagePath(descriptor, 100)).lastSegment()); + } + + /** + * The @2x variant is derived from the rewritten URL, so an icon pack only + * supplies the base name. + */ + @Test + public void testURLModifierIsAppliedBeforeHiDpiLookup() { + URL rectangular = FileImageDescriptorTest.class.getResource("/icons/imagetests/rectangular-57x16.png"); + URL zoomIn = FileImageDescriptorTest.class.getResource("/icons/imagetests/zoomIn.png"); + ImageDescriptor descriptor = ImageDescriptor.createFromURL(rectangular); + + ImageDescriptor.setURLModifier(url -> url.getPath().contains("rectangular-57x16") ? zoomIn : url); + + assertEquals("zoomIn.png", IPath.fromOSString(imagePath(descriptor, 100)).lastSegment()); + assertEquals("zoomIn@2x.png", IPath.fromOSString(imagePath(descriptor, 200)).lastSegment()); + } + + /** + * The scaled name fallback is derived from the rewritten URL too, so an icon + * pack is not mixed with platform icons at higher zoom levels. + */ + @Test + public void testURLModifierIsAppliedBeforeScaledNameLookup() { + URL zoomIn = FileImageDescriptorTest.class.getResource("/icons/imagetests/zoomIn.png"); + URL rectangular = FileImageDescriptorTest.class.getResource("/icons/imagetests/rectangular-57x16.png"); + ImageDescriptor descriptor = ImageDescriptor.createFromURL(zoomIn); + + ImageDescriptor.setURLModifier(url -> url.getPath().endsWith("/zoomIn.png") ? rectangular : url); + + assertEquals("rectangular-114x32.png", IPath.fromOSString(imagePath(descriptor, 200)).lastSegment()); + assertEquals("rectangular-86x24.png", IPath.fromOSString(imagePath(descriptor, 150)).lastSegment()); + assertEquals(114, descriptor.getImageData(200).width); + } + + @Test + public void testURLModifierIsAppliedToAdaptedURL() { + URL zoomIn = FileImageDescriptorTest.class.getResource("/icons/imagetests/zoomIn.png"); + URL rectangular = FileImageDescriptorTest.class.getResource("/icons/imagetests/rectangular-57x16.png"); + ImageDescriptor descriptor = ImageDescriptor.createFromURL(zoomIn); + + ImageDescriptor.setURLModifier(_ -> rectangular); + + URL adapted = Adapters.adapt(descriptor, URL.class); + assertNotNull(adapted, "URLImageDescriptor does not adapt to URL"); + assertEquals(rectangular.toExternalForm(), adapted.toExternalForm()); + } + + private static String imagePath(ImageDescriptor descriptor, int zoom) { + ImageFileNameProvider fileNameProvider = Adapters.adapt(descriptor, ImageFileNameProvider.class); + assertNotNull(fileNameProvider, "URLImageDescriptor does not adapt to ImageFileNameProvider"); + String path = fileNameProvider.getImagePath(zoom); + assertNotNull(path, "URLImageDescriptor ImageFileNameProvider does not return the " + zoom + "% path"); + return path; + } + +} From b04ad985da8d41bd3a19a7536d0a920fc0b98b25 Mon Sep 17 00:00:00 2001 From: Lars Vogel Date: Thu, 8 Oct 2026 11:18:44 +0200 Subject: [PATCH 2/2] Add an E4 RCP example that swaps icons through IImageURLModifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A declarative services component replaces the icons of the application model from a bundled pack, and a button selects the pack and restarts the workbench. Assisted-by: multiple AI agents and layers of automated tooling 🤖 --- .../.classpath | 7 + .../.project | 33 ++ .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 338 ++++++++++++++++++ .../org.eclipse.pde.ds.annotations.prefs | 8 + .../Application.e4xmi | 46 +++ .../Icon Pack Demo.launch | 37 ++ .../META-INF/MANIFEST.MF | 23 ++ ....examples.urlmodifier.IconPackModifier.xml | 7 + .../README.md | 10 + .../build.properties | 10 + .../css/default.css | 0 .../iconpacks/bold/copy_edit.png | Bin 0 -> 677 bytes .../iconpacks/bold/copy_edit@2x.png | Bin 0 -> 1197 bytes .../iconpacks/bold/delete.png | Bin 0 -> 669 bytes .../iconpacks/bold/delete@2x.png | Bin 0 -> 1399 bytes .../iconpacks/bold/home.png | Bin 0 -> 656 bytes .../iconpacks/bold/home@2x.png | Bin 0 -> 1218 bytes .../iconpacks/bold/paste_edit.png | Bin 0 -> 635 bytes .../iconpacks/bold/paste_edit@2x.png | Bin 0 -> 1227 bytes .../iconpacks/bold/redo_edit.png | Bin 0 -> 745 bytes .../iconpacks/bold/redo_edit@2x.png | Bin 0 -> 1573 bytes .../iconpacks/bold/refresh_nav.png | Bin 0 -> 783 bytes .../iconpacks/bold/refresh_nav@2x.png | Bin 0 -> 1664 bytes .../iconpacks/bold/save_edit.png | Bin 0 -> 621 bytes .../iconpacks/bold/save_edit@2x.png | Bin 0 -> 1073 bytes .../iconpacks/bold/undo_edit.png | Bin 0 -> 749 bytes .../iconpacks/bold/undo_edit@2x.png | Bin 0 -> 1588 bytes .../icons/copy_edit.svg | 151 ++++++++ .../icons/delete.svg | 83 +++++ .../icons/home.svg | 20 ++ .../icons/paste_edit.svg | 210 +++++++++++ .../icons/redo_edit.svg | 89 +++++ .../icons/refresh_nav.svg | 213 +++++++++++ .../icons/save_edit.svg | 20 ++ .../icons/undo_edit.svg | 84 +++++ ...rg.eclipse.ui.examples.urlmodifier.product | 26 ++ .../plugin.xml | 22 ++ .../urlmodifier/IconPackModifier.java | 39 ++ .../ui/examples/urlmodifier/IconPacks.java | 33 ++ .../urlmodifier/handlers/FakeHandler.java | 11 + .../urlmodifier/handlers/QuitHandler.java | 21 ++ .../urlmodifier/handlers/SaveHandler.java | 21 ++ .../urlmodifier/parts/SamplePart.java | 82 +++++ examples/pom.xml | 1 + 45 files changed, 1647 insertions(+) create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/.classpath create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/.project create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.core.resources.prefs create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.jdt.core.prefs create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.pde.ds.annotations.prefs create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/Application.e4xmi create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/Icon Pack Demo.launch create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/META-INF/MANIFEST.MF create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/OSGI-INF/org.eclipse.ui.examples.urlmodifier.IconPackModifier.xml create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/README.md create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/build.properties create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/css/default.css create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/copy_edit.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/copy_edit@2x.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/delete.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/delete@2x.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/home.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/home@2x.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/paste_edit.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/paste_edit@2x.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/redo_edit.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/redo_edit@2x.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/refresh_nav.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/refresh_nav@2x.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/save_edit.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/save_edit@2x.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/undo_edit.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/undo_edit@2x.png create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/icons/copy_edit.svg create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/icons/delete.svg create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/icons/home.svg create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/icons/paste_edit.svg create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/icons/redo_edit.svg create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/icons/refresh_nav.svg create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/icons/save_edit.svg create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/icons/undo_edit.svg create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/org.eclipse.ui.examples.urlmodifier.product create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/plugin.xml create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/IconPackModifier.java create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/IconPacks.java create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/FakeHandler.java create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/QuitHandler.java create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/SaveHandler.java create mode 100644 examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/parts/SamplePart.java diff --git a/examples/org.eclipse.ui.examples.urlmodifier/.classpath b/examples/org.eclipse.ui.examples.urlmodifier/.classpath new file mode 100644 index 00000000000..81fe078c20c --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/.project b/examples/org.eclipse.ui.examples.urlmodifier/.project new file mode 100644 index 00000000000..bf9ba539898 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/.project @@ -0,0 +1,33 @@ + + + org.eclipse.ui.examples.urlmodifier + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.core.resources.prefs b/examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.jdt.core.prefs b/examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..5f7f29a43c7 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,338 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=true +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.pde.ds.annotations.prefs b/examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.pde.ds.annotations.prefs new file mode 100644 index 00000000000..b5c60ed2648 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/.settings/org.eclipse.pde.ds.annotations.prefs @@ -0,0 +1,8 @@ +classpath=true +dsVersion=V1_4 +eclipse.preferences.version=1 +enabled=true +generateBundleActivationPolicyLazy=true +path=OSGI-INF +validationErrorLevel=error +validationErrorLevel.missingImplicitUnbindMethod=error diff --git a/examples/org.eclipse.ui.examples.urlmodifier/Application.e4xmi b/examples/org.eclipse.ui.examples.urlmodifier/Application.e4xmi new file mode 100644 index 00000000000..bbc5ff4f2df --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/Application.e4xmi @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/Icon Pack Demo.launch b/examples/org.eclipse.ui.examples.urlmodifier/Icon Pack Demo.launch new file mode 100644 index 00000000000..6dc8d371f22 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/Icon Pack Demo.launch @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/META-INF/MANIFEST.MF b/examples/org.eclipse.ui.examples.urlmodifier/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..fd71f4bcef0 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/META-INF/MANIFEST.MF @@ -0,0 +1,23 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Image URL Modifier Example +Bundle-Vendor: Eclipse.org +Bundle-SymbolicName: org.eclipse.ui.examples.urlmodifier;singleton:=true +Bundle-Version: 1.0.0.qualifier +Require-Bundle: org.eclipse.swt, + org.eclipse.e4.ui.model.workbench, + org.eclipse.jface, + org.eclipse.e4.ui.services, + org.eclipse.e4.ui.workbench, + org.eclipse.e4.core.di, + org.eclipse.e4.ui.di, + org.eclipse.e4.core.contexts, + org.eclipse.core.runtime +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Automatic-Module-Name: org.eclipse.ui.examples.urlmodifier +Bundle-ActivationPolicy: lazy +Import-Package: jakarta.annotation;version="[2.1.0,4.0.0)", + jakarta.inject;version="[2.0.0,3.0.0)", + org.osgi.service.component.annotations;version="[1.3.0,2.0.0)";resolution:=optional +Require-Capability: eclipse.swt;filter:="(image.format=svg)" +Service-Component: OSGI-INF/org.eclipse.ui.examples.urlmodifier.IconPackModifier.xml diff --git a/examples/org.eclipse.ui.examples.urlmodifier/OSGI-INF/org.eclipse.ui.examples.urlmodifier.IconPackModifier.xml b/examples/org.eclipse.ui.examples.urlmodifier/OSGI-INF/org.eclipse.ui.examples.urlmodifier.IconPackModifier.xml new file mode 100644 index 00000000000..6b1d5118df7 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/OSGI-INF/org.eclipse.ui.examples.urlmodifier.IconPackModifier.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/examples/org.eclipse.ui.examples.urlmodifier/README.md b/examples/org.eclipse.ui.examples.urlmodifier/README.md new file mode 100644 index 00000000000..bfc0e7a798f --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/README.md @@ -0,0 +1,10 @@ +# Image URL modifier example + +A minimal Eclipse 4 RCP application that swaps icons through an `IImageURLModifier` OSGi service. +`IconPackModifier` is a declarative services component, and the E4 workbench installs the service in JFace, so no startup code is needed. +The modifier looks up the file name of every requested icon in `iconpacks//` and returns `null` to keep icons the pack does not replace. +The pack replaces the part icon and the toolbar icons, which the application model loads from SVG files; the extra tool items use a handler that does nothing. + +The button in the part stores the selected pack in the instance preferences and restarts the workbench, since images that already exist are not reloaded. +Start it from `org.eclipse.ui.examples.urlmodifier.product` or with `Icon Pack Demo.launch`. +The launch configuration takes `org.eclipse.e4.ui.workbench.swt` from the workspace, which needs a version that contains the image URL modifier tracker. diff --git a/examples/org.eclipse.ui.examples.urlmodifier/build.properties b/examples/org.eclipse.ui.examples.urlmodifier/build.properties new file mode 100644 index 00000000000..1278ec60874 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/build.properties @@ -0,0 +1,10 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + .,\ + icons/,\ + iconpacks/,\ + css/default.css,\ + Application.e4xmi,\ + OSGI-INF/org.eclipse.ui.examples.urlmodifier.IconPackModifier.xml diff --git a/examples/org.eclipse.ui.examples.urlmodifier/css/default.css b/examples/org.eclipse.ui.examples.urlmodifier/css/default.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/copy_edit.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/copy_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..a8df26c528dbea2d50c1d9df8f931c26d45d6762 GIT binary patch literal 677 zcmV;W0$TlvP)|8AF?R|jfRz_UgTkBf zKck4!nIHT29*xn~V(F#ZueDnX?!f#%C*6hTkkNn-jnX zFR#7Q$%g04YRY6%AT*<#b(#~y@XE-1n+N6JZ?9Y)e5GT@%rD-$_j8Nx{;)8vpI8jR zqG1NkixiEUzt+SWBrqdpZq8L{db?11HavH8)K8wLCgZ90z1RwGeX=kkUzhOFtM?hN z8$Lja_{s_y?8)VxaR7)UiC85p!S$aiE_}Sf{XY`1Hpc5aGuGfFBvO=FXu8xCZ3*Py z+LelnpKoyJc$>Toe;2g~NcgX>vC2W)8O$xt1 z-5)Kk-o4|M4{EC9JON>`HopC0gOF`P3=mqoQKvl5uvCny!mSEm>EPO%z1Hw-QIDyu zL=u*a=|lTZ%5(F9UZ=-sdUxscM46!BJyr8pZ00000 LNkvXXu0mjfX5~ll literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/copy_edit@2x.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/copy_edit@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3cfd7e123d915832d68f5a657d4f07164500b4cc GIT binary patch literal 1197 zcmV;e1XBBnP)80dcC(qCnfJQ;^YCVNb~f|7(GU7CQ}wF8uCA`?0{S3| zsA~~*KiOtbsZd1&?8&{(YdVe(H~^^3af{}ihn>&#oKNo2?+2|yc7JTUUR{u-4v}hA z{6GR7g`=~J`vMgn@^pJW>_dQz<+v9FAP}gVBI+k6{=<{!%HIQQ+Y03ehY1gZdnNZsnk>O%Q#RDfy~1cWMcUej?b?!D))9WMpb z^Ql{PjdaO6CIq-{VS<(EJEm;fJFaE#+EQ44E1kXZS+y#@Qpq+iwTSvaEbi#+tv#VG zo=;uFQoI(3hybF-+pl*cRY=el%}mfp7GFJaai&(8J7Y}T6~C)hz{J(jac&bJX^sxN z2#_nus7w(M%CY4sJOVJri|_&fmAPwMY@+|tD%kFrQi+I7fCqMI?A&cY4o^du62F{H zV3U#QN&rHNHK9CFU6{ITG6QOdh}!OHArOcHS`Fgy=L}vsQW_Zn68PiC+en*)GVRkJ z5CxJxXG*4#uIvJk5$LPgJ_7HurPh~`EWy_z(^%m!r$aH2K!-%fvFcODIs}x?l2x_W zdNOPGXEOvg;)}y8Sp3JM)gWFtn8)7N@@+3b^Dfa?A#?!HV=YQ1C(r=~mXL`E+_>y; z^>+sX2=d)*QwDf)HbAouXx-hlNcPS0bq_rtHzpzw<^{?C(>oNN*&hPPjOL1hgQvIl z{pRaab)5UEiPDsSeQL!-1l9@@0haolZ8=_*^vHI0-}J` zJH*YuU2i2MAR3r{M33DmCnn$>kS_@?EhM_(aP?D7r0{~%YuG+*cX=Tc;{U#U&5?Ea( zyu-j8=p^ojM+!wmC2p0@`zrt-ojKs>o}1t0^|qIqcG-*cYrb8K`2+)yJ?YkwaG@$n z%iaC;w@0_{uEp>sLWCFqM4tk%UqpFi$vMz`Cj#R@R5t=7ozeL)vGvn&EbiDGjXDsE zi=vu7d4B3_GhO~v>+XZ3T?N9ST`AzFvNPPo@_Y=({J=+Haq5@SwpbBWZ7eKy)&ROZg~Eqea~Bv2!7o2)%*00000 LNkvXXu0mjfl#w`k literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/delete.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..bdab440effcc8a039b876bc3e8ea2e3fc915c6ed GIT binary patch literal 669 zcmV;O0%HA%P)DMl)hf-_kYqo$Uf_Ke`%R5@46>a%6&A#+U>CpfCzjzM0t*y&AKVs zTlc}9*(v+{?AbXYKCD2bloyMOI(FrX1X5i~?qY9G3)in}_S`wen>Se{8E`yL>Ej$A zB$pXJ8c|-jz|qxJ8l4V*2#8gR57`=I5tAj28qb+_6@RosA75CH}f|2hGfY#9(a=-`-~T(IZq8#DrZD(mlvN z?RI}F&CU$nos@Ea{W`L;{Ldkg=hBfQ^$bwCzf@f>*;h~lH=2^oNVydS#r(WXk|LxC znWTJfPFbr(0olZcqK6&ygCKvHHP=yA3gWLcO00000NkvXXu0mjf Du-88J literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/delete@2x.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/delete@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..93cbfa74802be0eaa1d7431bb3500203d7b09296 GIT binary patch literal 1399 zcmV--1&I2IP)0lB&BeX?gVcacj4U?ZhG%zOzNVoj?tu1WUH1^#ES0OhBj9*$KXk5vVr^?jIxA_@=z*(mx^Zr;4# zA|l`pp6xK$Ia)8;o()g5bX)wyKC_g^pN^M7w%LmG*F&kKb=W<~y0b1re|Z$}RMLqt_I znehE!)7rn}R#%t4o}c#(3k#{%xp#aKb*l6P_dJk8a1u$+_Rt_=VpS)q?<&ZjZrpGJ zX|`7yjoX1S#~Z5JMZoiLl?oDuNECr{y#T-%G>*|)4Kp&*^1CAnP1}hP$xRoF-x+{S zYfl=H<4Nj$m*;kKlgFNao^WOcx3h!zUDb>DK5l1+@YE?L-hLacR#T##Q4hLcyW;7v{8c6Zae_B`C~F5c7>C$C%~%;nI%J;q*p zjfuD3!fkIOy>sFr1e`;{kb1F5ytak}0UF1Iv$Ojov{plFwKn+dEE>ni&=7H{#P0R$ z$gyK+znmFJKoyB1;$o4zi;F3VFhuM1Hi_|Zyz%iic)gBi;EpzwnzYN&!Z>>UtGkN%Xp)s`+0Ko2($u`B$(mheG-lJ^)wRJ z5*7-Cg#v0V5{5L^*Z08>Ch4yt&>|t(EOujqJLk?(Us*wnL6aoa8AE+#g*)fYVK+9A zZ1zy#hbHiQ%Ap8|@1xZ!-sB`tUcE{*H-|ch_fEgQWK1;iXkUJ*g6#jd9Ztk{%n1z;;#(bb4M%A^W)JbB{RBQXF>Dk^o zJ7kPO^+Q=+w#?6aM!+tCH(f0Lv*O&}jt4=2YNF|O^k_>#HzlX4jmaPge@>DwPnSxc zFM%gFZX`mABFkVFfc1R-@~G#%T32PyIb5$RIf4k7ArUghP;u@bRnL26?$)hpQ`gS^ zgDcZoq3}`w=dJ1=B4ff|L!jMC3s@AF(MR%TBSy_9~$$|f@>3aT~Zbo0v&-a{6{|D^c+H?Xlf#3iD002ovPDHLk FV1h~Jye9J z>BJ9^k6;%yZZKrCf8W0M=32bXW{qCB%rL_}_nb3x1wdCY@(d49yE8JT9Z~)h5~`Hf z>%RwU;4?tMI8cuQff0rsRNH#@^k(C==puH{M%yLF#YRF3IE;a$3qcXF1$?WH6hp`| zfNaQN;*?*si|0&@Q)N`o#2!I#Vy#G;2x6rCU_(ZiKZ_}ZLbokqt%zV_k5QN~!=0I2 zq=**)W6`(`g(8*JEsB?}QaF2=(dAD_ID*D4Ft#TVuU0e%Km{>qr-=-mV)W@p3g@pt zmO_?Nm|vi>_7zi^M%#_tpPp4c1_sguJ26LP?F)tZg}m6hJhK!xbAih07ItzDO%o8| z7(mGnvM!Cc57Fj9UZ|RO=YS^#@ znLlPAh@uKEK*Ffk*`G+w?_7}I4>C|x6zNlzFv@*7W;y_@eSVUuxH5;eJ&meGVJtD$ zYp3oG)~+em4M-8lQnXVSjP-$0Vy`vHf}Q*;FP4_3hRyn63f;^@r}>Wy0uYw4#!x9j zwWUv{HXASc!?b%lx>qthik0aMV+Nh>$;9G)V5oLdUQKQ`p7)382;}F|RH>xR*+v(F q;BN-qE<^!z33kRe_763Gc>M!Wg%;I{@yPT50000tSP)ti;!k5+A%aeF!jqhIf4eFxw^>=OzgaHH%FtHj&5KKK(rz&qK$o~B} z0k~D%mc=ap?pqmcIj0QDv%%3BbqeQ3wI${z-xNo|*i zj0P@7=+;APRZM;-`QzV`KY0?}T z@XSTLvAx*sV+_B06>n@Wx>yG5$Fa0ZroTwrxsNWE@%B8*@H=wb{Ff-(d@TBIm|N$2m-{Kz`;DiHQTaa(oc|0azbbE|Hix zKz`;DCRbQP5P-9aHVoz5Z$?AaHTTogNGS<<&)?)b&;bUI_*g^^y;TzEGyri!3+*|9af#K zi9s7RGR32ja~DR2B}U1#Wn9S6k<(;~Z=&^DSKZDTP>1+Qnm=FT?$HTQCHK~OY+-kA zAT3@v{}+{0&qR3q6p~D}G7}d-WR2!8*Viu3X1%-Uz0|A|{P`mgT}hH0=qlQ?LL`-C z^=6kXtOO!a!M1g~MBf)cq}X09wn#B`<4?l>i2io~{YO=sTnH|R)dje4YXBrv>9>SS zW*AI7ypkF2$!~3=x(c8%X#eqQLD{pC-@Fq<-E-%Gjiv?sL+ldnnSfm>0je@H_!W_;kwsllb zfgH5pG%C&w@FkmzKMPbl)`3Ep_9Rhr@}8U{)JZ%ebA+=+?6z~&E9JWTXf!RpDuF`C z`j}l9?R;_0M(3)Eb4s(2lEj^w`)1_q;^(tPtXw6K7BZn2wd5U}{WzbH7way1m^h{T z7>hw7n6wqr9#k596$Gj03v=^Th{|Q{Wwh?eG(VMj&bM+TR3=hZ68Gy|fqJNcHT)Df z`C#=u`sT+B{AP+BBkrzPXwHY~j~?gY1pGh}HYL g0J_uV$<9OXU%t`|VH(oU0)+jEP)YcCW^AO;SuTSdEU8Pqz0piM^6 zqKGz9n+E)E%=q^`-@T{B%gHgNZ*lM8-t&EY=Yt~v6R4R)96;$(r7iYU0Vt56nq9FK znf}!p4y3hj}Y(^-e$j1iJ8CFKu{2bKKb)tBipqtCbv-|Jz zf-JX*l*?kf5@-vYn5xdW$~$gp4qL=G0n(G=EC@g#P*+6Mk4Ee}XTBf%8eqDYFhjui zse?ew-1O2ZR}If;EUycX~Yz(CC}{w*cfQ7<$GdiSfHG)jv~Q$*qLw}VfBgA7bYsD z*?GqaI*(t`%4KNk$Wtx?L``Dvoemy+ssOSR8SVLZpEU93FEQMLB=&EnPbkBdrSMgN z0Um-C04U8aj>e(>T`PCeFk*&)07@mJag8|m@DQGPdo@(XYqxlV z0ECp-@#K#3!uTH!0GLSa6H$|vF=S(62tWhWR+tc2C2Ca*YXDk6RJvxH z^5UpKbcTeGv_sB_(}=F!1|T7j3js_-?3z$G@_Z2@KpYa2`!$pXs5X3pbbiPm!tM7v zaJ=LbT>P|&YfBc|m97cYm4KuHH!`kpx=)LK>snI0Oe$(T>PYp}U)PDZ;=E=J&0j%T0M*sk#-vsc8h_XmN zjkK+(FAwGcwZ2ONlE%>mFO2JN1%a58vvkz4K#cEK^qF(x-!`L_4@SK`F2ES1LDGgp zJA;i>IZ0Z=M!UQTuO2Raar(lLbd@`A+erb>K23CO!HU;VJ)jy)UO79!gKVeKF_ z9!LlXM7gR6R~6ATE1!$gdivzTjrHWQaHE6PuS|1?t4})O9yd0=&(+25IkzK-$h2Y+ zeF-*x_l+OMKkn$-bTwi9>5hPZck}e!loyLWgN4 p%l1A^uI3yp^t+%mJD*$h{snIqFIKYc>S_Q0002ovPDHLkV1m^KMi&48 literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/redo_edit.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/redo_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..bef8b8dfc45c82df6d4a4d1bf37e6357eb71bc6f GIT binary patch literal 745 zcmVoTTnqnT-Z_wD0EZY6cJbLLJ&kS2D+&+!VvHaq?>f5 zODUz;g>FRDQdAIHp$iuxEyOB*VA7aLW+pT5&3o@27vuPW@xXxtm-FZR@A(}8pjIY1EQ22o?UyJvGi1Zr;P*uek#kt2M-O1*m zv2)aFMgS_4$GIJe4%`!kRBJ>ryJ|{31RRwFI5aJun{jHI)v%>lFwmNhFZz+VE zHBK@_oE4#yWh8lqLHMvzWxCxWv<@dG_klB{>2$a#>)o=2M*|8UX_^V(1d;hT=99q{ zY#3b0RQ)-7H*IAoia7B5C1S8;K~(jFxXc>&a!QZ%Y`3#6<6jIjzHOMu^`2)tZHA%} zpDrKd`|DTvccG3I@sj6i`u}8&p_#;dyKytezTClVr_IT~ZgTD6eTJeE0NX!a$N1;N zy^W{}Kz{;M6=y9YTei{8Qog?M3wNJA0c*Lk`#aWD2RM4`4=z8L!deU3+w>~|uS&rN ztSXgRND}VN{m=61GSVz(^!gR%;tn&dCe>o}78`vFSYuf1#@v4Pl-1=5`!;Q*lXeNL z@82sR-g_b!aCdfw z9lxF9;?zH6-Xqepw-noIt@J>ep1LDZaiex(Z;Wy6G}X*|%0ciZ(Ex&KP7pwv)?Fx{ z8TRbSQBDyAMuNb3RZ3wf1I40>G^(D)Jvj z5})U3p8FK9Dc-+MG{Klh`TYEN>)_#2ua2pIk*iLhE-$WNEv@bnj)5>F?1qo$Mn@Z{ b3L^Rf{R%TMZ9{hy00000NkvXXu0mjf3lm~Z literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/redo_edit@2x.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/redo_edit@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3e7afef15b87b827b2c902be16d40dce43a57e1b GIT binary patch literal 1573 zcmV+=2HN?FP)*<_JpbqQoClg=s9+fyvQ6g}f`I|kYCoAVQYcu4haJGp`}gN6cJd>{Rv;pI z&jEo|h#(zeQuade+dIY@LT10-he z>vQct|H)&L&+XDEa$2s$#Ie?yF8py$wOn>usm9Wg+mgE}^IHZ7Jp%)hSm3JW2llL! zRCrixwHWU$BJ(!8h@h&irWMs#a_uQMS$cSK`wxd07zhjuC(~YcVvVB8LWC;GN=Zr(qTt7zsu0^39EbT$G47?Ej9ocE-xr6-f+-Akk7Gnu+hGpwNq zf)X36w-&$m=otf0sb!ZS(u4C!*9sS5tX!rmli{l?R`JQ6#pJ^@=SveDzi^({&z;2@ z!`^%D=k~?7u;Z13d{COCJCh;yzU98xC6I)wFjlRwdCjMJbnQK?S=2LQ-OK+wLq1I7 zRr$v1PjPqe61E(Akwa%r)7h2YG-xSqTKjP^^^Me#ctAf9KuA-s4pX zjYWXVl`<(~uwsb4Z|E18_J8 z#g2}2y1A8SbAgCqZSO}>AZ0D*CMP)X)-iIq4gxWF_2koO%5jZtfBP$^zPXjjTEyO? zhxyIPe^9Jc=*(ou1|d$HXF^K?UKL{uw`AKJCVS`7C=*eYT=?OJvG)YVGFGiHaO4%9 z|L;4TzBEcM(?)k&TM`RRqW`)Cgru$)qiSPpNv?yGwGBUNV{P*N(_=?S2bS(^JI?!A z^ZzPZ7j6OX9dD0b0HEd_w{_pd11oN&I5D1-<0BU=l*l5 zo&kba<=6K=z(b$-43T%#{Pf&*sKoO-gURAc@|5df%-MQDBt_o}3<#d**6m;S=<|8;_mA79NKi+edYF^)B6 z-hM{`Z?r+cy6kypDq~`77tYPN6L?jO2wj;hCoX=#v2!C}EZHESJry>}^c+PSjjC!R z9RV;D3bwdo$C$wD5{3#iO~$RiYFas1>k-MnK!aFR+H414M8bL`$-?{w45Xtpi z)k(fH<%{Egp4k3_jr8>yhKJqN&4oh2P=MUU&pvIk*>4fYXcQ%8yD=CEQxJw|sr09e zFKxcKZTDm%RdlL$jh3nNmwPsOV;>QxcS;z9HzHkYaf~r1ar)%=ww=FA22~KbrZu~Y zDGg-)SNoPbA1za3gea0ZUtwb)3{|{W6UfMwE&Zn(f|2BIJS&EVEPBJfpN@fnru6?0 Xe6qz4cb(eT00000NkvXXu0mjfUL_In literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/refresh_nav.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/refresh_nav.png new file mode 100644 index 0000000000000000000000000000000000000000..6476c44be9c028f123ebb18bc741f071abe3d5f1 GIT binary patch literal 783 zcmV+q1MvKbP)a z+$o5dx{wH3u-XXfMx`rJaZwOautjLgOr2>m^Zk48x|k$X5YOst?&02Z?hyc5EyLns z1laM({-!DW%D>P6APx%o>)EsIn`dN`Onk8SfK-xGTE=MR(u#3;ELki1H2fItw9CR>53_IjL7xA1iHh~X*Sv{oxDs-=%k8Aw$kg6W zp<>0jLCB?99p}~ipX2eVJ)|KgXk@N=4^`(m_TB5Y%u2ChCfrDNhXX()iU@fu*j^du z+}<~s-8Mrf>*0)LJQ)Sxz|2Erq2R=Y(9=|B*UxCDJrd)HF$#biE&w4$>VAazsXesQE=xb1K@i$$kEgzAQD^|5 zViKISTLC-%2MUM?Su7ZF6}<6;4WUgK09CNYa3k+?{?Y}S)dr{Lp2mt$u?a_Z?c>h+ z4$_bfpW`OT&Xq^EXPLWboSiK4TpNB&K7VXz;`QtXQ6tT2gL8j=&y!!j!gw;OQB+VZ z3~_GDL{-HbMZsl0IU@QMw2SuI8oJrw`d-&*Q>?dhJ}xV#JD8h8sn{tswB?It+j?Y z>%`e1_bw3?5NE8ddyB}Mzb|~%HMCmh>fzN7dFLw^D_BPt8{{Rr^P1J=_JnR4f N002ovPDHLkV1jshd8_~c literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/refresh_nav@2x.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/refresh_nav@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..256cf2ba5f7f9dc1db240d79b5c9d5b6e92cbf3c GIT binary patch literal 1664 zcmV-`27md9P)quf~ zNNwUjqy*b2ElroyKxi>&6MosWR$D7sV+l|YiWC->ot>TCoq6xx;~z7-?6Nz{Lcht& zOy0Zqp6@;PobNdo#zRNW(vh>{e!CfHyQ#NcFs|`6yBxr@j$E_G{WCFM05qxoUJnu& z9r_=q!;1yU_Y4z}ydO1o)XesFLq6}@UVM0o3Csq(-iOm$#*CXR1Tb7e%sY5}_TswN z-x#r$jwVps`LrDmZ8A~t6jso(1E*sbu4hjKMQcmfU&wSTO`*F=8-ch-^qP?q}_tU*-8FKV!g^iG7R}GkU6GGy05uaE%lxYgm zB7hMr0vQ^O2v?)WmxW-j86%&j1BviBTE z&cDy%w!3iZSvmVY{`kPJS$p7@Tplct2^&egt9k+Tk`97&iMa(hEdZa|@!$fB{oopw z!!TmFQZBN3&QkJsKhFH@ZS_tFfW$ijV>wnh!#Dr(Q%?4tqb17JVnV&714GHJxbWD% z17^aN04tWBa*>UnTg%QBdFE$tqvGQ+?-4)?1TiW zZZGnUIZN2I_y;(3ICX?3MKSK@tqYyJeX)~5rEi#oQ;!iLvMB&ml^@=vw@jy3;cPwn3$KjP*hmF2}`8Y40*w4}K z6CCR~LrrNemw**Rp;F}AcYcN0&9_kTF`-GZ{n%cfII@}6C`(h&K8pZ(L&UnZL5{>|1#CG^ZMv*3g1iMQcwzOhBNT=kqeN5Cjq7-`%G;KX8er zpkX-ZsxB3#hMD2?@#=@t?z*T;;6^bNV4lerFPI<;1fk*+J}myP7J#15w$5c{LmL%0 zT4s$@Jrw)oTKWAX1QdgC;QV_CLZXf-sU|jlejVNA0%aEu*Mfnh%wSSsT0;wkN(n2I zZ>H)JaO%mV8rgsLZO-(4Ov(hrKH>2NkMP|6KcOw1r9T;@KN)0tLo3gGX#ZsqH< z@8!ZkH%2B`Oed7$A^l%<`~AGU;#as@QL$nv#{G15e+a2{@vg4o6c8g z3ewk>WNt``oqAfr47*Ps=I8&|h82qyOU1`zQjOd*VzaJ+DqU%b1WS5FvRG46_S5Iq{VfTLz zbLjj(dEnDuxLS^Zlf`o!JpUeVeDrs&REo5vv!jaB7${)nYEznhVO2{MR8C<{%gr<- z6`x=bGO0!aV<$2`6kn>Ee5UKWe?DR8$l1d8_VfUMlh7*EpIxnVhN)48wkS(;s*&bY zBW+QZsZjhL6A`%qD5@US*i21_u2A0Fwf;{# z$mJ}{4<$oqEp+4z!1Qw8cGDa_rm;sWj!EZJU5Js;B9XXghNDn$GEyqkZYPqW6D}e->Bo%{0;g0000< KMNUMnLSTZ>*)+TW literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/save_edit.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/save_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..ccfeb9e2f1b9a062c06e048eeb206e1ed49346e2 GIT binary patch literal 621 zcmV-z0+RiSP)m8!aq|9gU5~1|=rO&cedP z_%9e@qK#1(H7bIjK+qL;-@bdt;_>)cc9KaZ_ug~vIWrjnV9JzR5&(`}-RRYt87(5j zBJb{XukOZ3UW{E>oRDJqhJ|E=5Ck#V3l~GwM2id7*t}DDIPi!mQvo<~@y9uh`=171 zM?xKS3TBW~7$8FM0n;K{=)l*0U9LRnpAja_jduNfrG?HDmQ>R;5dE#SbU-N(~gMXGz0noX2$&&|9JZ~b?sUgpg&bT9I>TN zL`YI&@PIOLI?j}D36U);&tBGf{n6-%1;m1QvncOS{xJ2~kBe)8rBx5W!CuFq9wqfV zWLSpD3ARHOoWgLQGTf*8?wVtpAcU+*a~~RjU$lw!q)76iHcpP2%@9n1I-Ss>lDzM(>M400000NkvXX Hu0mjfdpsa3 literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/save_edit@2x.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/save_edit@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..784460bc526f9cc23a8ea4d5c51a6b9feecdf169 GIT binary patch literal 1073 zcmV-11kU@3P)7YOf7UHbg5v(tsrg&K??p9DFlKmT@}(H8(j$%h1SL* z7KCJ_(w($+A!v66QEQW?iqNL9NfVk(X6D}eb@67JnaRwXd1(bdxD3oY_nhyZpL@;) zI-y97B6Y`ayTKGyH+^QO@mY;IaR6{+f4e`1OT7}0zwrVkKJB)=k|0E0D*a(pL$vX(7dm<>_m5)ph4<4{Q+SP89xL`VuAan2HZCjgudKZ|Mc7p`W}hTfpnx zxjhjiX-%{@@SFGE`1AbO?D*7Wql)#f&dUc-0ZET`<061cxjN7n5h%Kfr^tr@Br?0Vjy8x&;z&bX{W2+kn0o*dp-`e?V4Xkbu@4ueK zVuy#9D zNx&H3`GY~~;!Q<>jN^N>5OgL8B*y!(2{apeQuu!-p>x1+B)D*C3m30eQr`o^k-+r` zNg@FP&y^SHf|rW1C(3DXg1kO&MA27)v$c+@{1hk(|xD<@u!aO{-`&c**Fp&@hO zQW>9LEF(9R9EL;!&As5+ed$KT(GdmbdpoRW2n0a27T0&0UQn&|SFXKtfIv1B7~R`A zuq~4frT-kDgLI-o#tC@yj>XS^)Zlzv6-j8w+`MBEm~M$kAnxw5mkzwOx+gTXMNwuC zz1=a8R2^V#%7MfP!ma}e=;5DRn0abmp*XAm`YLxHlwZUQ5b;dbvLiIWU{)}gk@z=h z)n!7{k*gOo;6eZU!ur@ENKrsM6)G_wfe?!F?dK!`pK^6_Jwc~Tq@eW2m=iaC3R+=K z9E!90`b_ReS6w?B4CDin7NG0H;r)OhJ?U#fG#a|{^7l8+?fn|XS$(A>w$afA#kesQ zhF8v+%*fkx6?j_)=zWs*o)A%DA}ABVZLNPBWU9x0`)q8Z{wiQosct`+3ddL8RLV?} z_Nda?aM%5pgm)DyO8@GeKRrK_JHKtK{b|-f(*yGGiSjefmk-d3fHoZsF%(5YqJQSk rMhoqSOx|3i-WGl`7$3jf@zQ$;whnDKkmnvD!I;H-W#vNmopTq5%e1kPqn9t&dOO)mH~oJ&1>%@Ejqfd= fInzc}5Yhht1kgWypwZ<_00000NkvXXu0mjf_BdlL literal 0 HcmV?d00001 diff --git a/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/undo_edit@2x.png b/examples/org.eclipse.ui.examples.urlmodifier/iconpacks/bold/undo_edit@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d462b0a749dc7c53129a1d55febba405b95f202 GIT binary patch literal 1588 zcmV-42Fv-0P)%l^!Mv#>!}4J`MhCh$O2rvYge{nrY|El3L=vK zCBQQR5rhHSH>1TbY#E;=GBDtp6R1zf?%IB%^89;o?gpIeZb)<~Pzn?U(fW{a@=)>a zzWsC7lKBJ%2MxWww*7}Y?pI-OA4Vfl4Xj<3?OAAz3IafoYP4r^v~)KB0|Nqx1`@aT z_S(!3zIVUs$lfPWWTjk*iDRiVUH;Enk#gBer5daD>|NQ5Qjah&;OOsHi3etOzI(?8 zD06JfFzF;*@yR+?t4 zTw=Uh#Ub-ZHS~huR2X=%b5{a*t!8^#Gghf^X*$EhAKl2O*S?$Ku{W8FA~vk*VcjL& zbf>cvqbjc!Mmg}`|1e%IlS`$rON^6-1QZGsjFqOjW%b+HbIZrMs-qJpLPrqt%TX-#(~OLr!V z6^9e>wZ@8I#c}P*E`EONCs=>UD!%&MGqi`{q8T%ffKm$Q9HB8hx#?4UxMwx7b0C6O z*H!>qCu0e^aycuFx9RXKLHz-5^%0GFmSXsvNA0YJvxk{9(ZyMG~C8FmVj^bGq> z40GhnDY8L`Z%lLT1#nts2^gC`V|8U*X_Ld+1$Tl*up(sqfTv%7jlHiO184C)pIj=9 z6W7eR09vA|m`F|nX!3be+_Gg{!JkwR2+&%z^H%e;CKrZurZclLGpKHJS(L?X_&%R_}D`-BA0^?R!*i#TTVG zQ3G_nkT0((na@!Wv8rQ*?~0SZp4$BNP4xC^hKB6S;);A;lZWgZ>wl`#={t#IB#IKZ zT^O_qdHVK&uP@0000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + backpaper + + + page-lines-back + + + frontpaper + + + page-lines + + + fold + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/icons/delete.svg b/examples/org.eclipse.ui.examples.urlmodifier/icons/delete.svg new file mode 100644 index 00000000000..b76f1ad4eb7 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/icons/delete.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + x + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/icons/home.svg b/examples/org.eclipse.ui.examples.urlmodifier/icons/home.svg new file mode 100644 index 00000000000..06a9eaeaf06 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/icons/home.svg @@ -0,0 +1,20 @@ + + + + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/icons/paste_edit.svg b/examples/org.eclipse.ui.examples.urlmodifier/icons/paste_edit.svg new file mode 100644 index 00000000000..47e168ce59d --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/icons/paste_edit.svg @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + clipboard + + + clasp + + + paper + + + paper-fold + + + paper-lines + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/icons/redo_edit.svg b/examples/org.eclipse.ui.examples.urlmodifier/icons/redo_edit.svg new file mode 100644 index 00000000000..b38686f672a --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/icons/redo_edit.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + redo-arrow + + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/icons/refresh_nav.svg b/examples/org.eclipse.ui.examples.urlmodifier/icons/refresh_nav.svg new file mode 100644 index 00000000000..4abb2d68c02 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/icons/refresh_nav.svg @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/icons/save_edit.svg b/examples/org.eclipse.ui.examples.urlmodifier/icons/save_edit.svg new file mode 100644 index 00000000000..223536d8022 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/icons/save_edit.svg @@ -0,0 +1,20 @@ + + + + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/icons/undo_edit.svg b/examples/org.eclipse.ui.examples.urlmodifier/icons/undo_edit.svg new file mode 100644 index 00000000000..2ebc181569d --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/icons/undo_edit.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + undo-arrow + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/org.eclipse.ui.examples.urlmodifier.product b/examples/org.eclipse.ui.examples.urlmodifier/org.eclipse.ui.examples.urlmodifier.product new file mode 100644 index 00000000000..6d7c55ce558 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/org.eclipse.ui.examples.urlmodifier.product @@ -0,0 +1,26 @@ + + + + + + + + + + -clearPersistedState + + -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts + + + + + + + + + + + + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/plugin.xml b/examples/org.eclipse.ui.examples.urlmodifier/plugin.xml new file mode 100644 index 00000000000..fb802de0111 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/plugin.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/IconPackModifier.java b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/IconPackModifier.java new file mode 100644 index 00000000000..6b8c44de2fd --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/IconPackModifier.java @@ -0,0 +1,39 @@ +package org.eclipse.ui.examples.urlmodifier; + +import java.net.URL; + +import org.eclipse.jface.resource.IImageURLModifier; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; + +/** + * Replaces any icon whose file name exists in iconpacks/<pack>/ of this + * bundle. + */ +@Component +public class IconPackModifier implements IImageURLModifier { + + private Bundle bundle; + private String pack; + + @Activate + void activate(BundleContext context) { + bundle = context.getBundle(); + pack = IconPacks.selected(); + } + + @Override + public URL modifyURL(URL url) { + if (pack == null) { + return null; + } + String path = url.getPath(); + String name = path.substring(path.lastIndexOf('/') + 1); + int dot = name.lastIndexOf('.'); + String baseName = dot < 0 ? name : name.substring(0, dot); + // null keeps the original icon + return bundle.getEntry("iconpacks/" + pack + "/" + baseName + ".png"); + } +} diff --git a/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/IconPacks.java b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/IconPacks.java new file mode 100644 index 00000000000..00378cd1308 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/IconPacks.java @@ -0,0 +1,33 @@ +package org.eclipse.ui.examples.urlmodifier; + +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.osgi.service.prefs.BackingStoreException; +import org.osgi.service.prefs.Preferences; + +/** Stores the icon pack selected for the next start. */ +public final class IconPacks { + + public static final String BOLD = "bold"; + private static final String KEY = "iconPack"; + + private IconPacks() { + } + + private static Preferences preferences() { + return InstanceScope.INSTANCE.getNode("org.eclipse.ui.examples.urlmodifier"); + } + + public static String selected() { + return preferences().get(KEY, null); + } + + public static void select(String pack) throws BackingStoreException { + Preferences preferences = preferences(); + if (pack == null) { + preferences.remove(KEY); + } else { + preferences.put(KEY, pack); + } + preferences.flush(); + } +} diff --git a/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/FakeHandler.java b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/FakeHandler.java new file mode 100644 index 00000000000..08f113badf1 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/FakeHandler.java @@ -0,0 +1,11 @@ +package org.eclipse.ui.examples.urlmodifier.handlers; + +import org.eclipse.e4.core.di.annotations.Execute; + +/** Does nothing; the tool items using it only show icons. */ +public class FakeHandler { + + @Execute + public void execute() { + } +} diff --git a/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/QuitHandler.java b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/QuitHandler.java new file mode 100644 index 00000000000..890879ceb1d --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/QuitHandler.java @@ -0,0 +1,21 @@ +package org.eclipse.ui.examples.urlmodifier.handlers; + +import java.util.List; + +import org.eclipse.e4.core.di.annotations.Execute; +import org.eclipse.e4.ui.workbench.IWorkbench; +import org.eclipse.jface.dialogs.PlainMessageDialog; +import org.eclipse.swt.widgets.Shell; + +public class QuitHandler { + @Execute + public void execute(IWorkbench workbench, Shell shell) { + + PlainMessageDialog dialog = PlainMessageDialog.getBuilder(shell, "Confirmation") + .message("Do you want to exit?").buttonLabels(List.of("Exit", "Cancel")).build(); + + if (dialog.open() == 0) { + workbench.close(); + } + } +} diff --git a/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/SaveHandler.java b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/SaveHandler.java new file mode 100644 index 00000000000..b086e410753 --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/handlers/SaveHandler.java @@ -0,0 +1,21 @@ +package org.eclipse.ui.examples.urlmodifier.handlers; + +import org.eclipse.e4.core.di.annotations.CanExecute; +import org.eclipse.e4.core.di.annotations.Execute; +import org.eclipse.e4.ui.workbench.modeling.EPartService; + +public class SaveHandler { + + @CanExecute + public boolean canExecute(EPartService partService) { + if (partService != null) { + return !partService.getDirtyParts().isEmpty(); + } + return false; + } + + @Execute + public void execute(EPartService partService) { + partService.saveAll(false); + } +} \ No newline at end of file diff --git a/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/parts/SamplePart.java b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/parts/SamplePart.java new file mode 100644 index 00000000000..35f67df29ce --- /dev/null +++ b/examples/org.eclipse.ui.examples.urlmodifier/src/org/eclipse/ui/examples/urlmodifier/parts/SamplePart.java @@ -0,0 +1,82 @@ +package org.eclipse.ui.examples.urlmodifier.parts; + +import java.util.Arrays; +import java.util.List; +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; + +import org.eclipse.e4.ui.di.Focus; +import org.eclipse.e4.ui.di.Persist; +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.workbench.IWorkbench; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.widgets.ButtonFactory; +import org.eclipse.jface.widgets.LabelFactory; +import org.eclipse.jface.widgets.TextFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.examples.urlmodifier.IconPacks; +import org.osgi.service.prefs.BackingStoreException; + +public class SamplePart { + + private TableViewer tableViewer; + + @Inject + private MPart part; + + @Inject + private IWorkbench workbench; + + @PostConstruct + public void createComposite(Composite parent) { + parent.setLayout(new GridLayout(1, false)); + + String pack = IconPacks.selected(); + LabelFactory.newLabel(SWT.NONE) // + .text(pack == null ? "Icon pack: none (default icons)" : "Icon pack: " + pack) // + .create(parent); + ButtonFactory.newButton(SWT.PUSH) // + .text(pack == null ? "Use the \"bold\" icon pack and restart" : "Use the default icons and restart") // + .onSelect(e -> switchPack(pack == null ? IconPacks.BOLD : null)) // + .create(parent); + + TextFactory.newText(SWT.BORDER) // + .message("Enter text to mark part as dirty") // + .onModify(e -> part.setDirty(true)) // + .layoutData(new GridData(GridData.FILL_HORIZONTAL))// + .create(parent); + + tableViewer = new TableViewer(parent); + + tableViewer.setContentProvider(ArrayContentProvider.getInstance()); + tableViewer.setInput(createInitialDataModel()); + tableViewer.getTable().setLayoutData(new GridData(GridData.FILL_BOTH)); + } + + private void switchPack(String pack) { + try { + IconPacks.select(pack); + } catch (BackingStoreException e) { + throw new IllegalStateException(e); + } + workbench.restart(); + } + + @Focus + public void setFocus() { + tableViewer.getTable().setFocus(); + } + + @Persist + public void save() { + part.setDirty(false); + } + + private List createInitialDataModel() { + return Arrays.asList("Sample item 1", "Sample item 2", "Sample item 3", "Sample item 4", "Sample item 5"); + } +} \ No newline at end of file diff --git a/examples/pom.xml b/examples/pom.xml index d362711e645..d0a0f69639c 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -38,6 +38,7 @@ org.eclipse.ui.examples.readmetool org.eclipse.ui.examples.undo org.eclipse.ui.examples.uriSchemeHandler + org.eclipse.ui.examples.urlmodifier org.eclipse.ui.examples.views.properties.tabbed.article org.eclipse.ui.forms.examples org.eclipse.ui.genericeditor.examples