Icon rendering issues with HTMLEditorKit when Darcula UI theme is selected, Same Icons work fine when Default is the UI theme.
I have spent the better part of the day trying to figure out this icon rendering bug and beginning to suspect that it is something behind the scenes that I am not aware of. Any help will be greatly appreciated.
In my MultiMarkdown plugin I use HTML <INPUT TYPE=CHECKBOX> to create task lists and custom bullets that are rendered by HTMLEditorKit. I set the icons for the control after creation: normal, disabled, selected, disabled-selected. Everything works fine if the Application Theme is Default.
I allow the user to select the HTML Preview Theme separate from the Application theme and both HTML Preview default.css and darcula.css work as expected when UI is Default. The only difference between the two stylesheets is color settings, I did a diff just to make sure. The icons all have _dark.png, @2x.png and @2x_dark.png variations. On my retina mac the hires icons are used, as expected. Here are the two stylesheets rendered with Default Application UI:
However, when I switch the Settings Appearance to Darcula this is what I am getting for the custom Icons and themes. The painting of them is offset and that is definitely not in my code since I provide the icons as files and they are fine. I have tripple and quadruple checked what they look like in IntelliJ IDEA, and all icons have the same dimensions and image placement within the tile, the issue is really in how they are rendered when the Theme is Darcula.
When I create the component for the FormView:
c = super.createComponent();
JCheckBox chk = (JCheckBox) c;
Icon openTask = isInverted ? MultiMarkdownIcons.OPEN_TASK_INV : MultiMarkdownIcons.OPEN_TASK;
Icon closedTask = isInverted ? MultiMarkdownIcons.CLOSED_TASK_INV : MultiMarkdownIcons.CLOSED_TASK;
chk.setIcon(openTask);
chk.setDisabledIcon(openTask);
chk.setSelectedIcon(closedTask);
chk.setDisabledSelectedIcon(closedTask);
c.setEnabled(false);
The icon ending in _INV has the same set of icons as the non-inverted version but they are reversed, _INV has dark ones, _INV_DARK has light ones. They are physical copies of the non-inverted icons. I use them when the Preview Theme and the Application theme are opposites so that the right icons get selected by IconLoader.getIcon(). I use a bash script to make the copies:
#!/usr/bin/env bash
ICONS=./src/main/resources/com/vladsch/idea/multimarkdown
cp $ICONS/bullet.png $ICONS/bullet_inv_dark.png
cp $ICONS/bullet_dark.png $ICONS/bullet_inv.png
cp $ICONS/bullet@2x.png $ICONS/bullet_inv@2x_dark.png
cp $ICONS/bullet@2x_dark.png $ICONS/bullet_inv@2x.png
cp $ICONS/opentask.png $ICONS/opentask_inv_dark.png
cp $ICONS/opentask_dark.png $ICONS/opentask_inv.png
cp $ICONS/opentask@2x.png $ICONS/opentask_inv@2x_dark.png
cp $ICONS/opentask@2x_dark.png $ICONS/opentask_inv@2x.png
cp $ICONS/closedtask.png $ICONS/closedtask_inv_dark.png
cp $ICONS/closedtask_dark.png $ICONS/closedtask_inv.png
cp $ICONS/closedtask@2x.png $ICONS/closedtask_inv@2x_dark.png
cp $ICONS/closedtask@2x_dark.png $ICONS/closedtask_inv@2x.png
I have eliminated all posibilities that I could think of and don't know what else to try. Any help or pointers would be greatly appreciated.
请先登录再写评论。
This is definitely something in IntelliJ handling of icons. I used the IntelliJ UI theme and all the icons are completely overriden by that scheme. So I disable Icons for Darcula as a workaround as the only solution for now.
Hi Vladimir,
if you're going to use images in html viewer then forget about IconLoader. It won't help you here.
We had pretty similar problem in Tips & Tricks component and I use the following trick there to show correct images. For Retina displays we should show <img width="50%" height="50%" src="path_to_image@2x.png"/> Unfortunatelly, Java editor kit doesn't recognize 50% value, so we should calculate absolute values. Please take a look at TipUIUtil.updateImages()
So, use <img src="path_to_resource"/> and use predefined values for width and height. I believe it's easy in your case as you have not so many icons.
Thank you very much for the information. I will use your approach to solve the problem.
Thank you Konstantin. I implemented your suggestion in the last release and it works like a charm. Using pixel sizes was not an issue because all the icons are the same size.
Since the plugin already subclassed HTMLViewFactory and HTMLImageView to properly resolve document relative image URLs, I was able to use UIUtil.isRetina() for automatic selection of HiDPI versions of the images.
I would have liked to use list-style-image in the CSS but in the end list item paints an image by creating an ImageIcon() from the URL and I was back at square one. So your solution is the only reliable way to bypass IDEA's low level icon image swapping based on retina setting and darcula UI scheme.