Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Allow plugin fragments to supply alternate icons #14

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

AObuchow
Copy link
Contributor

Fix #13

Allow plugin fragments to contribute alternate icons that will be loaded
through the URLImageDescriptor class.

The icons must be placed within a directory titled "theme"
located at the root of the plugin fragment, ie. "/theme/"

The file path of the replacement icons must match the file path of the
icon to be replaced.

For example, in order to replace an icon used by plugin org.eclipse.xxx
where the path of the icon is "/path/To/icon.png" in the plugin's bundle
one must:

  • Create a plugin fragment with org.eclipse.xxx as the Host Plug-in
  • Create a directory "/theme/" at the root of the plugin
    fragment
  • Place an alternate icon with the correct file path in the theme
    directory, ie. "/theme/path/To/icon.png"

Allow plugin fragments to contribute alternate icons that will be loaded
through the URLImageDescriptor class.

The icons must be placed within a directory titled "theme"
located at the root of the plugin fragment, ie. "/theme/"

The file path of the replacement icons must match the file path of the
icon
to be replaced.

For example, in order to replace an icon used by plugin org.eclipse.xxx
where the path of the icon is "/path/To/icon.png" in the plugin's bundle
one must:
- Create a plugin fragment with org.eclipse.xxx as the Host Plug-in
- Create a directory "/theme/" at the root of the plugin
fragment
- Place an alternate icon with the correct file path in the theme
directory, ie. "/theme/path/To/icon.png"

Signed-off-by: Andrew Obuchowicz <[email protected]>
@AObuchow
Copy link
Contributor Author

Here is the original Gerrit (it has some comments which are still valuable).

@AObuchow
Copy link
Contributor Author

In order to test out this PR:

  • Checkout the PR locally, having the JFace Eclipse bundle imported
  • Clone my sample icon-providing fragment
  • Import the sample fragment into your Eclipse workspace
  • Ensure the Eclipse application has all workspace plugins enabled (Or atleast, JFace and the sample fragment)

The observed result should be that the "run" and "debug" icons in the toolbar have been replaced:
image

@mickaelistria
Copy link
Contributor

The overall code seems good. What particularly is left TODO (apart from the documentation TODO in code) ?

Copy link
Contributor

@laeubi laeubi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes to much specific assumptions (icons are always local bundles, they can be resolved to a path, we know how image URLs are constructed,...).

I think it should more work with a delegation model where we construct an new URL for the theming and using the original one as a fallback image in case of errors.

if (
// !JFaceResources.getString(JFacePreferences.CUSTOM_RESOURCE_THEME).equals(JFacePreferences.CUSTOM_RESOURCE_THEME)
// &&
resultingURL.getFile().contains(PLUGIN_URL)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is suitable to explicitly target the (internal) plugin URL format. We should use a scene that is independent from the source URL format like it is done with the zoom images.
The one don't needs to fiddle around with bundle ids and nls and alike...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 with that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm +1 for doing that, as it simplifies things a lot.
However, I'm a bit confused on how to do this, since the requirements and assumptions for zoom images are different.

For zoom images, resolution-specifying directories (eg icons/32x32/) only need to come from the same bundle as the original icon. Thus it is possible to preprend the icon filename with the resolution-specifying directory, and keep the rest of the icon URL/filepath the same.

With themed icons, the requirements is to allow another bundle (that is different from the original bundle which provides the icon) to provide an alternative icon URL. Thus, we need to change the bundle in the icons URL. My original idea was to provide a JFace preference (CUSTOM_RESOURCE_THEME) which would specify which bundle is providing the alternative icon.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For zoom images, resolution-specifying directories (eg icons/32x32/) only need to come from the same bundle as the original icon.

This depends on the URL type used. You can use http urls as well or even custom url types (like mvn:)

With themed icons, the requirements is to allow another bundle (that is different from the original bundle which provides the icon) to provide an alternative icon URL. Thus, we need to change the bundle in the icons URL.

If you want to replace icons from a bundle, the most flexibel way would be to require that providers supply a fragment to this bundle, that is how the translation bundles work (it would even allow to provide different sizes right now) and then you can simply modify the name.

This of course would mean there is not only one icon bundle but different ones, on the other hand it is a standard way to enhance an existing bundle and would make it clear what icons are included, so one don not need to ask the icon supplier to add support for my special eclipse plugin but I can supply an own one (probably once included in the original icon pack).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to replace icons from a bundle, the most flexibel way would be to require that providers supply a fragment to this bundle, that is how the translation bundles work (it would even allow to provide different sizes right now) and then you can simply modify the name.

This of course would mean there is not only one icon bundle but different ones, on the other hand it is a standard way to enhance an existing bundle and would make it clear what icons are included, so one don not need to ask the icon supplier to add support for my special eclipse plugin but I can supply an own one (probably once included in the original icon pack).

My worry with making the icon provider have to supply a fragment to the original icons bundle is that it would require many icon bundles to replace all of Eclipse's standard icons. This would probably demotivate icon pack creators as it'd be very tedious, rather than creating a single plugin that replaces icons from various bundles (even though my idea contradicts the name of this PR).

With that being said, I am open to your approach as a "first step" towards supporting icon replacement in Eclipse. Perhaps a script/tool could be developed to automate the process of creating the required bundle fragments and populating them with the replacement icons.

@gayanper @mickaelistria if either of you have any input on this, feel free to chime in :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My worry with making the icon provider have to supply a fragment to the original icons bundle is that it would require many icon bundles to replace all of Eclipse's standard icons.

The problem is, that each bundle has its own class/resource space so bundle A and B can have both icon/editor.png also note that there is no such thing as "all" icons because Eclipse can be extended and different combinations are used.

So it would be better to be more flexible here and tyr to give icon-pack creators tools to easier organize/automate this process, e.g. I can think of something like the babel-project for icon, where a tool simply scans a folder of plugins and discovers all image resources, then this is presented to the user as a big table and icons can be replaced and sutable fragments are generated, an update site is prepared and then one can install the packs required for the current eclipse install.

Beside this, I tried a while back to get SVG support into SWT (with little success because of concerns having a dependency to AWT), that would allow to style icons with CSS and could be even more profitable as you do not need to edit/replace every icon ...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a first iteration, as there is no API, I think it's OK to restrict the them-ability to plugins/fragments and consider opening it to other URI schemes later.

PLUGIN_URL + bundleID + THEME_REPLACEMENTS_DIR + originalFilePath);
String found = getFilePath(themedIconURL, false);
if (found != null) {
resultingURL = themedIconURL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes more sense to simply return here instead of fall through the default return.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

try {
URL themedIconURL = new URL(resultingURL.getProtocol(), resultingURL.getHost(), resultingURL.getPort(),
PLUGIN_URL + bundleID + THEME_REPLACEMENTS_DIR + originalFilePath);
String found = getFilePath(themedIconURL, false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that filepath is suitable here, this further limits the usage of this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My intention here was to validate that the newly constructed icon URL actually resolves, and if not, fallback to the default icon. Do you know if there is a better way to see if a URL resolves, that doesn't rely on the assumption that bundles are local?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah maybe instead of getFilePath(themedIconURL, false) I could do something like URLImageDescriptor.getImageData(themedIconURL)? I'm investigating your commit for help :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only way that works for all cases is try open the URL, and maybe fall back to either the error or the original URL.

@@ -42,6 +42,9 @@
*/
class URLImageDescriptor extends ImageDescriptor {

private static final String THEME_REPLACEMENTS_DIR = "/theme"; //$NON-NLS-1$
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why limit to one particular folder here and not use what is provided by the CUSTOM_RESOURCE_THEME

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, the parent directory of the icon should be as customizable as possible for the theme creator/provider.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 with @laeubi proposal to not mandate a root directory and let path just be /mySuperIconTheme/path/to/image.png

@mickaelistria
Copy link
Contributor

Thanks @laeubi for the review; I agree with those points, and trying to stick to (any form) of URL should work better.

@AObuchow
Copy link
Contributor Author

Thanks for the review @mickaelistria :)

The overall code seems good. What particularly is left TODO (apart from the documentation TODO in code) ?

I think asides from addressing @laeubi's comments, there are some followup tasks that will come from this change.

Some that come to mind are:

  • Set defaults for the newly created JFace Preferences (one preference should probably specify the icon theme bundle, and another will specify the parent directory of the themed icon)
  • Add an extension point to set these above two preferences in an icon theme bundle
  • Add an extension point to associate an icon theme to an IDE theme (this would allow specifying icons to use for the dark theme, and different icons to use for the light theme)
  • Add a UI preference to select the icon theme, similar to how IDE themes are chosen.

@AObuchow
Copy link
Contributor Author

@laeubi Thank you very much for the review :) I apologize for being so slow on this topic. I hoped it was just a matter of me implementing your requested changes, but it turns out I needed further clarification.

@vogella vogella mentioned this pull request Jun 16, 2022
@gayanper
Copy link
Contributor

gayanper commented Aug 3, 2022

@AObuchow are you planning to continue on this PR ? it would be really good to have this functionality to start creating some icons packs with the themes.

@AObuchow
Copy link
Contributor Author

AObuchow commented Aug 5, 2022

@AObuchow are you planning to continue on this PR ? it would be really good to have this functionality to start creating some icons packs with the themes.

Thanks for pinging me on this @gayanper :) Yes I am planning on continuing it, I just got caught up with life shortly after my last comments. Feel free to help contribute to this topic in any way, it is always appreciated :)

@@ -42,6 +42,9 @@
*/
class URLImageDescriptor extends ImageDescriptor {

private static final String THEME_REPLACEMENTS_DIR = "/theme"; //$NON-NLS-1$
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 with @laeubi proposal to not mandate a root directory and let path just be /mySuperIconTheme/path/to/image.png

if (
// !JFaceResources.getString(JFacePreferences.CUSTOM_RESOURCE_THEME).equals(JFacePreferences.CUSTOM_RESOURCE_THEME)
// &&
resultingURL.getFile().contains(PLUGIN_URL)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a first iteration, as there is no API, I think it's OK to restrict the them-ability to plugins/fragments and consider opening it to other URI schemes later.

// TODO: This is a workaround and should probably be removed
if (originalFilePath.contains("/$nl$/")) { //$NON-NLS-1$

originalFilePath = originalFilePath.replace("/$nl$/", "/"); //$NON-NLS-1$ //$NON-NLS-2$
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is $nl$ removed here? I think it should be kept and resolved as usual without particular case.

@akurtakov
Copy link
Member

Is there any hope for this one still?

@AObuchow
Copy link
Contributor Author

Is there any hope for this one still?

Yes, I apologize for the extremely long delay. I believe the remaining changes that are required are relatively simple, I've just been putting it off due to personal priorities. I will try and make these changes over the next week.

Since the consensus is to keep things relatively simple and rely on plugin fragments, I will follow this approach:

So it would be better to be more flexible here and try to give icon-pack creators tools to easier organize/automate this process, e.g. I can think of something like the babel-project for icon, where a tool simply scans a folder of plugins and discovers all image resources, then this is presented to the user as a big table and icons can be replaced and sutable fragments are generated, an update site is prepared and then one can install the packs required for the current eclipse install.

vogella pushed a commit to vogellacompany/eclipse.platform.ui that referenced this pull request Feb 14, 2023
…platform#14)

* Bug 579509 - IES423:(ICT) Missing space between two strings
- Fixed missing space between strings
- Added missing Eclipse Copy right note

Change-Id: Ie3bbd2ff42172d1cd5beb0269900cda1039e07d4
Signed-off-by: Niraj Modi <[email protected]>

* Bug 579509 - IES423:(ICT) Missing space between two strings
- Fixed missing space between strings
- Added missing Eclipse Copy right note

Change-Id: Ie3bbd2ff42172d1cd5beb0269900cda1039e07d4
Signed-off-by: Niraj Modi <[email protected]>
HannesWell pushed a commit to HannesWell/eclipse.platform.ui that referenced this pull request Jul 1, 2023
@akurtakov
Copy link
Member

@Michael5601 This might be interesting for you as you deal with icons now.

@Michael5601
Copy link

Michael5601 commented Nov 27, 2024

@Michael5601 This might be interesting for you as you deal with icons now.

Thanks for the info. Seems like a great project. :)

Yesterday I talked with a colleague of mine about this topic as he searched for a new bigger project. This would fit perfectly with our new initiative for a new modern icon pack in the Eclipse IDE. @gayanper maybe you are interested in participating as you talked about new icon packs?

I will forward this PR to my colleague as I probably won't have time due to other projects.

@jannisCode
Copy link
Contributor

Hi guys, I was asked if I could continue with this PR. First of all I would like to know if my ideas are realistic before starting to implement them.
My vision would be the following: In the settings there is a drop down (like currently with the dark/light theme). From there one can select a specific folder from which the icons should be taken.
I would like to create a folder structure with a base folder /icons in which the folders of the icon themes lie (e.g. /icons/default or /icons/modern) in each of the icon-folders, all eclipse icons are saved, with the same name (default and modern would both have a icon called run_exc.png). This structure would make it rather easy to switch between the iconThemes. The question would just be: where to create the base folder?
Also I see it as an important change, which is why I would maybe change the existing solution, so that it is not a Plugin/fragment but fully and by default integrated in eclipse.
The way I understand it, the switching of icons already works with this PR, so I could use the functionality which @AObuchow already made.
Please feel free to point out things that i missed and/or understood incorrectly, I am really looking forward to working on this issue!

@mickaelistria
Copy link
Contributor

My vision would be the following: In the settings there is a drop down (like currently with the dark/light theme). From there one can select a specific folder from which the icons should be taken.

I think how users interact with this feature is a next step. IMO it can be skipped for the moment so we can focus on the more critical underlying design. Once we have the ability to switch to another icon set, one way or the other, then we'll more easily figure out how far we want to push it in term of usability. But anyway, usability cannot be implemented until underlying strategy is available in JFace.

would like to create a folder structure with a base folder /icons in which the folders of the icon themes

Sounds good.

all eclipse icons are saved

Note that it's about improbable that all plugins change their icons dir. So the icons/<setName> folder should be queried first, but if no icon is found in there, then the "root" directory should be used as fail back.

where to create the base folder?

The current proposal of a fragment is convenient with plugin URLs because from a plugin it's easy to infer the path of the plugin and the path of the icon to inject the icons/<setName> indirection in it.
But ideally, this would work for any kind of icon and any URL. But the more general case would be much harder to implement ( https://github.com/eclipse-platform/eclipse.platform.ui/pull/14/files#r971998765 ), hence -unless you have a string need for it- I suggest to sticking to icons with a plugin URL for the moment. Maybe later that could be improved, but I think it would be relatively difficult to find a solution that doesn't require to change all consumers; so it's likely that the balance of difficulty vs profit can be found just by supporting plugin URLs.

@laeubi
Copy link
Contributor

laeubi commented Dec 2, 2024

If we use a URL scheme than all kind of URLs should/could be supported, I don't see that a specific scheme is mandatory for this.

Anyways for me the most interesting part would be how to derive the theme id (in a platform independent way) and one should keep in mind that this can increase the load time of images a lot.

@mickaelistria
Copy link
Contributor

I don't see that a specific scheme is mandatory for this.

Imagine file:/path/to/a/folder/or/maybe/an/application/and/another/random/path/before/that/which/might/be/or/not/an/icon/folder/or/the/root/folder/of/icon/resources/icon.png, how do you establish which URL you want to try for alternative icons? Try them all?
The benefit of more constrained schemes is that we know where is the root of resources.

the most interesting part would be how to derive the theme id

I guess it would be more the other way round with the given proposal: there would be a named icon set, existing in the wild independently from the theme, and any Eclipse theme could declare to use that set.

@laeubi
Copy link
Contributor

laeubi commented Dec 2, 2024

how do you establish which URL you want to try for alternative icons? Try them all?

As we do for other schemes as well, e.g currently we support

  • NxM folders
  • @x<Z> names

so for sure one can take your provided example here, extract the name part and try

file:/path/to/a/folder/or/maybe/an/application/and/another/random/path/before/that/which/might/be/or/not/an/icon/folder/or/the/root/folder/of/icon/resources/<themeId>/icon.png

or even

file:/path/to/a/folder/or/maybe/an/application/and/another/random/path/before/that/which/might/be/or/not/an/icon/folder/or/the/root/folder/of/icon/resources/<themeId>-icon.png

or whatever, I think this is the most important part is should/must work with all kinds of URIs.

If you only want support for resources loaded from bundles, then a Resource Hook would be much better suited as I mentioned already somewhere before.

@merks
Copy link
Contributor

merks commented Dec 2, 2024

Of course there is already built-in support for platform:/plugin/<bsn>(_<bundle-version>)?/

image

Anyway, I'm not sure why we are discussing file: URLs instead of platform: or bundleentry: as are generally used to access resources within a bundle. Maybe we digress. 😜

Translation support has similar issues about looking things up at alternative locations and to which fragment can contribute "overrides"...

@laeubi
Copy link
Contributor

laeubi commented Dec 2, 2024

Translation support has similar issues about looking things up at alternative locations and to which fragment can contribute "overrides"...

This is a different topic, because here we are talking about URLImageDescriptor... not about BundleImageDescriptor, or EclipsePlatformImageDescriptor or... as said if only bundle contents is to be assumed then better use a ClassLoaderHook and you can (dynamically) provide alternative resources without changing a single line of platform code.

@mickaelistria
Copy link
Contributor

then better use a ClassLoaderHook and you can (dynamically) provide alternative resources without changing a single line of platform code.

That does seem very interesting!

@jannisCode
Copy link
Contributor

Hi guys, i am currently working on this issue and encountered a problem with the bundleentry - URL´s. Some of the URL´s are not of the type platform:/plugin... but rather of the type bundleentry://301.fwk1538988266/icons/....
My current approach is to modify the url so that it finds the icon in a specific (new) plugin or just finds it directly in the normal plugin in a folder with the icons from the theme (Both should work). Anyways I need to know the name of the plugin that holds the default icon.
Right now I use FileLocator.toFileURL(url) to get the physical storage-place and then I try to find the plugins name from there(bundleentry://301.fwk1538988266/icons/full/elcl16/javaassist_co.png is modified to platform:/plugin/IconsPlugin2/modern/org.eclipse.jdt.ui/icons/full/elcl16/javaassist_co.png ). This approach works, but it is not really a nice solution and for a few icons, that have a strange storage-place the solution does not work.
Do you have any ideas how i could handle that problem? Or have you noticed any problems with this solution?

Thanks for the help!

@laeubi
Copy link
Contributor

laeubi commented Dec 20, 2024

My current approach is to modify the url so that it finds the icon in a specific (new) plugin or just finds it directly in the normal plugin in a folder with the icons from the theme (Both should work). Anyways I need to know the name of the plugin that holds the default icon.

As mentioned already above, one can not make any assumptions about the actual URL, as it is a URLImageDescriptor and not an Icon, Bundle or whatever one.

Right now I use FileLocator.toFileURL(url)

Also assume it can be converted to a file is plainly wrong, from my point of view as again there is no guarantee about what this actually return.

So I can only strongly suggest to only operate on the URL itself (as it is done for the NxM scheme and for the @x<Z>) if one want something that works in general and not only in some cases.

@merks
Copy link
Contributor

merks commented Dec 20, 2024

FYI, I think toFileURL would unzip and jar to some local location...

@Michael5601
Copy link

Also assume it can be converted to a file is plainly wrong, from my point of view as again there is no guarantee about what this actually return.

What is the workflow if the bundleentry://-URL can't be converted to a path?
The icon needs to be loaded from somewhere right?

My experience with Eclipse icons was that they are either loaded via a ImageFileNameProvider directly with the file path that is provided by DPIUtil.validateAndGetImagePathAtZoom() or they are loaded via a ImageDataProvider. The process of the ImageDataProvider involves turning the bundleentry://-URL to a file path with FileLocator.toFileURL(url).

@laeubi
Copy link
Contributor

laeubi commented Dec 20, 2024

What is the workflow if the bundleentry://-URL can't be converted to a path?
The icon needs to be loaded from somewhere right?

They are not converted to a path, they are just loaded form the URL#openStream() that is how URLs work, they are abstractions over an (unknown) transport.

My experience with Eclipse icons was that they are either loaded via a ImageFileNameProvider directly with the file path that is provided by DPIUtil.validateAndGetImagePathAtZoom() or they are loaded via a ImageDataProvider. The process of the ImageDataProvider involves turning the bundleentry://-URL to a file path with FileLocator.toFileURL(url).

Just look at org.eclipse.jface.resource.URLImageDescriptor.getImageData(String, int) for example. It all operates on the Filename or path of the URL.

@merks
Copy link
Contributor

merks commented Dec 20, 2024

Note that both these schemes are hierarchical just like file: scheme is hierarchical so I would imagine you can do the same/similar things with the URIs as you are trying to do with the paths...

@laeubi
Copy link
Contributor

laeubi commented Dec 20, 2024

I'll try to setup an example using bundle transformer hooks the next days, this looks actually more useful than having even more URLs to check and it should even use for all kind of ways to access the icons.

@Michael5601
Copy link

They are not converted to a path, they are just loaded form the URL#openStream() that is how URLs work, they are abstractions over an (unknown) transport.

Makes sense, thank you for the clarification. :)

@laeubi
Copy link
Contributor

laeubi commented Dec 21, 2024

I have now setup an example locally and technically we have everything we need already in platform but it could be improved so it works a little bit smoother for the case of an icon pack, the only thing we need here is some kind of documentation and an example. From that we can start creating icon packs and probably improve the process further.

The good thing about this is that it is totally flexible regarding the icons to replace and the layout to be used, does not require "special" things like fragments and one can choose to replace icons for one bundle or even all bundles.

The only thing is that when one installs multiple packs that try to override the same icons then of course only one can win, but that's more a deployment issue.

@mickaelistria
Copy link
Contributor

mickaelistria commented Dec 21, 2024

the only thing we need here is some kind of documentation and an example.

Ideally, we could start with some test cases. Using an eg blue square icon by default in an ImageDescriptor and testing it to be overridden as a red icon by a theme could be a relatively easy way to test we get the right image.

Do I get it right that your proposal then would be purely available for URLs from Equinox, and not for general SWT then? (note that I don't think it's an issue, having theming implemented in Platform rather than in SWT makes at least as much sense as the other way round)

@laeubi
Copy link
Contributor

laeubi commented Dec 21, 2024

It has nothing to with ImageDescriptor or SWT at all and will work for BufferedImage or whatever technique is used as it replaces the resource on the bundle level by an alternative one.

So it won't work if you use SWT/JFace in a plain setup without OSGi, but as there you have a flat classpath it is even simpler: Just make sure your icon pack appears before the one you want to replace an image.

@jannisCode
Copy link
Contributor

@laeubi thanks for your support with the two issues! Because i still am pretty new to eclipse, and don´t have as much knowledge as you guys, maybe someone could explain to me how I can use @laeubi ´s issues to reach my goal of a working icon-theming.
Thanks in advance!

@BeckerWdf
Copy link
Contributor

I have now setup an example locally and technically we have everything we need already in platform but it could be improved so it works a little bit smoother for the case of an icon pack, the only thing we need here is some kind of documentation and an example. From that we can start creating icon packs and probably improve the process further.

Thanks for that. I don't have the technical knowledge the really understand your implementation on a technical level.

The good thing about this is that it is totally flexible regarding the icons to replace and the layout to be used, does not require "special" things like fragments and one can choose to replace icons for one bundle or even all bundles.

For the "Icon Packs" I see two use-cases:

  1. You are delivering a RCP product and you want to replace Platform's icons with your own company styled icons. So you need to ship a plug-in or an fragment e.g. called "com.acme.iconpack" that replaces icons e.g. from the "org.eclipse.ui" plugin

  2. The Eclipse Project delivers multiple icon packs (e.g. exiting "classic" icons and additional "monochrome" icons). You are extending the Eclipse IDE with some bundles that provide editing support for your own fancy programming language. You also want to deliver icons that contribute to the Platform's "monochrome" icon pack inside your bundles.
    For example in your "com.acme.fancyEditor" plugin you have existing icons in the normal

/icons
  /etool16
    log.png
    [email protected]
  /obj16
    fancyType.png
    [email protected]

folder structure. And you want to simply add new monochrom versions of "log" and "fancyType" directly inside the com.acme.fancyEditor" plugin.

The only thing is that when one installs multiple packs that try to override the same icons then of course only one can win, but that's more a deployment issue.

From the user's perspective the icon pack should be something he selects in the preference dialog. For example a new setting next to the "Theme" drop down box on the "Appearance" preference page. This drop down box would list all available icon packs and the user can select which one to use. So only one icon pack should be "active" at a time.

Can you explain e.g. based on my example if and how these use-cases can be achieved? What does an plugin-developer do to leverage this feature?

@laeubi
Copy link
Contributor

laeubi commented Dec 25, 2024

I'll prepare an example how this can be used once the changes are available but don't wanted to rush them in due to holiday seasons and give people some more time to possibly give feedback.

In any case things like configurability / UI is something that has to be provided on top of this and we might want/need to further enhance the "core" for different use-case, but both of what you have described is possible.

@HeikoKlare
Copy link
Contributor

From the user's perspective the icon pack should be something he selects in the preference dialog. For example a new setting next to the "Theme" drop down box on the "Appearance" preference page. This drop down box would list all available icon packs and the user can select which one to use. So only one icon pack should be "active" at a time.

I want to share/refresh one conclusion we had at last year's Eclipse IDE community day at SAP when discussing the icon exchange/pack/theme topic: Due to the general independence of plugins, being provided as extensions to a product like the IDE, it is unlikely to achieve one consistent set of new icons under the same icon pack/theme ID (or even multiple ones, if new types of icons are provided). If we consider "icon packs" as complete sets of icons, all provided for the same ID of an icon pack, this probably only work fine for the product use case, where the product delivers a complete and consistent icon pack on its own, but not when considering an extensible platform.

Last year, we thus agreed on following the approach of making icon packs modular and choosing multiple of them to form something like an icon theme. For example, the Eclipse platform may deliver a "flat" and "monochrome" icon pack. JDT does the same. Some extension provider only provides a "flat" pack. Now you can select those packs you want to combine to your theme. One reasonable theme would be the combination of all "flat" icon packs. But given that the extension provider has no "monochrome" pack so far, you could combine its "flat" pack with the other "monochrom" ones, rather than using the default (non-flat) icons, which do integrate with monochrome icons even worse, when just allowing to contribute to a complete icon theme.

In addition, icon packs may not be mutually exclusive, as an icon pack may want to override an icon that is also provided by another icon pack, like the one with the basic icons for the platform. This may be resolved by defining a precedence order for the icon packs.

image

And to make it easier to configure, you may still think of a concept of "themes" that have a default configuration for specific icon packs or icon pack IDs, but still give users the flexibility to insert the desired icon pack with icons of an extensions for which no "properly matching" icon pack is provided.

@laeubi
Copy link
Contributor

laeubi commented Dec 30, 2024

Yes multiple packs can work together, one pack might even be able to override the ones from another, but as mentioned these are more "organizational" things, e.g. m2e allows to install so called "connectors", the same is possible for team providers (SVN, GIT) so maybe that would be a better approach than a plain preference.

I'll leave that to the interested parties after the technical thing is available :-)

@BeckerWdf
Copy link
Contributor

I'll leave that to the interested parties after the technical thing is available :-)

But how can we make "technical things" available "before" we agreed on what we want to offer to the user?

@laeubi
Copy link
Contributor

laeubi commented Dec 30, 2024

I'll leave that to the interested parties after the technical thing is available :-)

But how can we make "technical things" available "before" we agreed on what we want to offer to the user?

If the requirement is that we can replace icons by alternative ones through other bundles without the help of the original bundle author, then this can be solved independent on how these "icon bundles" later being installed or how many of them there are and how the UI looks like.

And as @HeikoKlare correctly summarized, as Eclipse is extensible there is actually no way to have "one" icon pack that solves that all... maybe there will be one that supports many famous extensions but it can't support everything.

This is not necessarily a problem, as still a dedicated product or EPP on the other hand still can benefit from such a feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for "Icon Packs"
10 participants