Open husker-dev opened 4 years ago
I have found the worst solution - recreate Component
and apply skin again.
This does sound like a weird issue, i'll check this tomorrow and see if I can include a fix in v1.2.11 update.
I found the problem - skin styles compilation happens a bit too late and that causes an issue with the part in StyleManager
that applies compiled styles to existing components. It basically starts to ignore existing components once skin has changed.
I will fix this issue shortly so it won't appear in v1.2.11 anymore.
Code I used for testing this case:
public class StyleEditorTest
{
public static void main ( final String[] args )
{
SwingTest.run ( new Runnable ()
{
@Override
public void run ()
{
final WebPanel container = new WebPanel ( new BorderLayout ( 0, 15 ) );
container.setPadding ( 15 );
final WebButton button = new WebButton ( StyleId.of ( "preview" ), "Sample button" );
container.add ( button, BorderLayout.NORTH );
final WebSyntaxArea editor = new WebSyntaxArea (
"<skin xmlns=\"http://weblookandfeel.com/XmlSkin\">\n" +
" <id>husker.editor.skin</id>\n" +
" <class>com.alee.skin.light.WebLightSkin</class>\n" +
" <supportedSystems>all</supportedSystems>\n" +
" <title>Custom skin</title>\n" +
" <description>WebLaF Editor Skin</description>\n" +
" <author>Husker</author>\n" +
"\n" +
" <include nearClass=\"com.alee.skin.light.WebLightSkin\">resources/web-light-skin.xml</include>\n" +
"\n" +
" <style type=\"button\" id=\"preview\" extends=\"ico\">\n" +
" <painter>\n" +
" <decorations>\n" +
" <decoration>\n" +
" <WebShape round=\"0\" />\n" +
" </decoration>\n" +
" </decorations>\n" +
" </painter>\n" +
" </style>\n" +
"\n" +
"</skin>",
SyntaxPreset.xml, SyntaxPreset.editable, SyntaxPreset.base, SyntaxPreset.historyLimit
);
container.add ( editor, BorderLayout.CENTER );
new DocumentChangeBehavior<WebSyntaxArea> ( editor )
{
@Override
public void documentChanged ( @NotNull final WebSyntaxArea component, @Nullable final DocumentEvent event )
{
try
{
final XmlSkin xmlSkin = new XmlSkin ( ( SkinInfo ) XmlUtils.fromXML ( editor.getText () ) );
StyleManager.setSkin ( xmlSkin );
}
catch ( final Exception e )
{
e.printStackTrace ();
}
}
}.install ();
TestFrame.show ( container );
}
} );
}
}
I've added fix for this issue and also an extra fallback for skin installation to ensure that everything else works correctly after new skin installation failed.
This fix will be available in v1.2.11 update which will be released today or tomorrow.
I have got the same issue in 1.2.11 after wrong extends
:
<skin xmlns="http://weblookandfeel.com/XmlSkin">
<id>husker.editor.skin</id>
<class>com.husker.editor.app.skin.CustomSkin</class>
<supportedSystems>all</supportedSystems>
<title>Custom skin</title>
<description>WebLaF Editor Skin</description>
<author>Husker</author>
<include nearClass="com.alee.skin.light.WebLightSkin">resources/web-light-skin.xml</include>
<style type="button" id="preview" extends="icon" />
</skin>
com.alee.managers.style.StyleException: Skin 'husker.editor.skin' doesn't have any styles for component type: button[class javax.swing.JButton, ButtonUI, class com.alee.laf.button.WButtonUI, class com.alee.laf.button.WebButtonUI, StyleId [ id: 'button'; parent: null ]]
at com.alee.managers.style.data.SkinInfo.getStyle(SkinInfo.java:453)
at com.alee.managers.style.XmlSkin.getStyle(XmlSkin.java:159)
at com.alee.managers.style.AbstractSkin.removeSkin(AbstractSkin.java:81)
at com.alee.managers.style.StyleData.removeSkin(StyleData.java:456)
at com.alee.managers.style.StyleData.applySkin(StyleData.java:293)
at com.alee.managers.style.StyleData.applyCustomSkin(StyleData.java:349)
at com.alee.managers.style.StyleManager.setSkin(StyleManager.java:1276)
at com.alee.managers.style.StyleManager.setSkin(StyleManager.java:1260)
at com.husker.editor.app.skin.CustomSkin.lambda$applySkin$1(CustomSkin.java:57)
at java.lang.Thread.run(Thread.java:748)
Do you also get it in my code example from above?
To check it:
ico
to icon
-> style should apply correctly nowI useStyleManager.setSkin(JComponent, XmlSkin)
inside the new Thread
and it works almost fine except for wrong extends
value.
If I use StyleManager.setSkin(XmlSkin)
it works fine with extends
everytime, but inside new Thread
my application freezes.
For my application I prefer change skin in new Thread
(Your example works fine)
That is actually pretty bad, I mean changing skin on a separate Thread
- it has to be done on EDT, just like any other operations with Swing. It is important because when skin is changed it applies itself to all existing components one by one and that involves a lot of work with UI elements. You can mostly work with Swing outside of EDT, but the risk is on you - once UI is big enough you're guaranteed to run into issues and weird exceptions. Same with WebLaF and any UI-related managers or features - I can only guarantee they will function correctly when run on EDT.
So I strongly recommend switching the skin setup to run on EDT and see if it solves your problem or not.
I also have a tool in place with which you can check that you're not running something that should be run on EDT on some other Thread
- Forced EDT usage - you can enable the checks and see where your application crashes. Those places are also recommended to be run on EDT.
Just a note - running stuff on EDT is not really a WebLaF requirement, it is purely dictated by Swing framework. You can check official note in Swing tutorials about EDT usage.
Considering that WebLaF generates thousands of events when skin is being replaced - it is highly possible that you will run into issues with it more often than you normally will with Swing when operating outside of EDT.
I understand what are you writing about, but that is different issue. I mean you have fixed issue when style applied to every component, not to one.
Here is comparison (after wrong extends
value):
StyleManager.setSkin(JComponent, XmlSkin)
:Thread
: Exception!
new Thread(() -> {
SkinInfo skinInfo = XmlUtils.fromXML(text);
StyleManager.setSkin(component, new XmlSkin(skinInfo));
}).start();
EDT
: Exception!
SwingUtilities.invokeLater(() -> {
SkinInfo skinInfo = XmlUtils.fromXML(text);
StyleManager.setSkin(component, new XmlSkin(skinInfo));
});
StyleManager.setSkin(XmlSkin)
Thread
: Freeze (OK)EDT
: OKApplying skin to one of the components is still strange.
Ok, that makes sense, it's been a while since I actually applied skin to a particular component so I totally missed it in your comment. Thanks for pointing it out :)
I'll try it and see if I can reproduce & fix the problem quickly.
I found the source of problem, but it's quite a tricky thing, I'll need some time to figure out how to change it to fix the per-component skin usage (there are actually a few different problems, but in case of editor you're only seeing one of them).
As a temporary solution - you can call install ()
on your loaded skin before applying it:
final XmlSkin xmlSkin = new XmlSkin ( ( SkinInfo ) XmlUtils.fromXML ( text ) );
xmlSkin.install ();
StyleManager.setSkin ( component, xmlSkin );
This will ensure that corrupted skins do not break component information stored internally in StyleManager
.
Just to clarify - install ()
call on Skin
doesn't really install it as the current application skin, it will simply initialize all internal data necessary for the skin to function and in case there are some faulty styles you will receive an exception which will halt further application of that skin to any components.
This bug actually revealed a few big flaws with the current implementation of the styles loading and usage. The good thing is - I was planning to change behavior overall anyway for the next update, so I will be working on that for quite some time, but as a result it should fix these issues and also improve initialization performance, so loading skin from the XML will be extremely fast.
Moving this to v1.2.12, not yet sure if fix will be implemented earlier or at the same time as the performance improvements for skin initialization.
When I apply my style to a
WebButton
with wrongextends
value I get an exception and the button dissapears - it's ok, but after that, when I apply the style with correctextends
value I also get an exception andWebButton
doesn't appear.Is there way to return back this
WebButton
?Here is my log:
Wrong
extends
valueCorrect
extends
value