Is the `svgResource` function expected to work in ...
# compose-desktop
c
Is the
svgResource
function expected to work in the context of a Compose Desktop app running in an IntelliJ plugin? I tried adding a simple SVG into the
resources
directory, using the IDEA plugin example, then referenced it in an
Icon
. I get this error now from
openResourceStream
Copy code
java.lang.IllegalArgumentException: Resource circle.svg not found
	at androidx.compose.ui.res.Resources_desktopKt.openResourceStream(Resources.desktop.kt:23)
	at androidx.compose.ui.res.DesktopSvgResources_desktopKt.svgResource(DesktopSvgResources.desktop.kt:48)
	at com.jetbrains.compose.ComposableSingletons$ComposeDemoActionKt$lambda-1$1.invoke(ComposeDemoAction.kt:60)
	at com.jetbrains.compose.ComposableSingletons$ComposeDemoActionKt$lambda-1$1.invoke(ComposeDemoAction.kt:54)
I don’t have the fullest working knowledge of how resources are loaded, but I bring it up since when using resources in the same directory with just
Window
and
main
it just works.
o
It’s general resource loading logic, and shall work the same way as with other resources.
c
So I tried to call
vectorXmlResource
(pointing to a vector drawable in
resources
instead of an SVG), and the same problem. I think it’s because both functions under the hood call
openResourceStream
which is where the resource path issue is happening.
I’m able to repro this in this example from the examples folder: https://github.com/JetBrains/compose-jb/tree/master/examples/intelliJPlugin
1
What I do is add an SVG or vector drawable to the
resources
folder in the project, then point to it using an
Icon
composable in this function: https://github.com/JetBrains/compose-jb/blob/master/examples/intelliJPlugin/src/main/kotlin/com/jetbrains/compose/ComposeDemoAction.kt#L52
I don’t know if it’s the code in the example that is causing the issue, but there isn’t any code from me that is highly custom at this point.
o
does workaround Igor suggested help?
s
I also have faced this issue, with all forms of trying to load images from resources from an Intellij plugin context, everything leads to
ERROR - llij.ide.plugins.PluginManager - Resource * not found
The work around did not help for me at least
1
c
TBH @olonho and @Igor Demin I’m not clear on the workaround linked above. This is my code that I added to the IDEA plugin example:
Copy code
Icon(
    imageVector = vectorXmlResource("ic_circle.xml"),
    contentDescription = "Circle icon"
)
Can anyone else repro this with the IDEA plugin example on GitHub?
s
Actually the workaround that Igor posted works, here is how i got it to work:
Copy code
// Called from DemoDialog
    ImageComposable(classLoader = this@DemoDialog::class.java.classLoader)

    @Composable
    fun ImageComposable(classLoader: ClassLoader) {
        Thread.currentThread().contextClassLoader = classLoader
        Image(
//          bitmap = imageResource("some_image.png"), // If you want to use an ImageBitmap
            imageVector = vectorXmlResource("some_image.xml"),
            contentDescription = "Sample",
            modifier = Modifier.fillMaxSize()
        )
    }
🙏 1
i’m not sure if
ClassLoader.getSystemClassLoader()
was supposed to be used as he described, but passing the classloader from the dialog instead works for me
c
Ohhh gotcha - let me try that. Thanks!
👍 1
s
it seems that it is also possible to just use the classloader of any class that is currently running e.g
DemoAction
/
DemoDialog
directly, rather than having it as a parameter
Copy code
Thread.currentThread().contextClassLoader = ComposeDemoAction::class.java.classLoader
👀 1
c
So that worked in the simple IDEA plugin example! But now does that mean I need to pass this
ClassLoader
instance all the way down my Compose hierarchies to the call site of
vectorResource
svgResource
, etc?
Since the Compose hierarchies all are built with functions and not classes…
s
using the last example worked for me without the need for having the classloader as a parameter
c
Nice - yes it worked for me!
🎉 1
Now looking back at the linked thread, I better understand the single threaded comment
I guess the way I’m interpreting this is by putting this call basically at the very root of your Compose hierarchy, it sets the context for the rest of the hierarchy since Compose is single-threaded?
Copy code
Thread.currentThread().contextClassLoader = PluginAction::class.java.classLoader
s
That’s my understanding as well. One thing i am not sure about is
You can call 
Thread.currentThread().contextClassLoader = ClassLoader.getSystemClassLoader()
 there, not in Composable function.
I tried this but it didn’t work, only when i specified it at the root of the hierarchy did it work
also
ClassLoader.getSystemClassLoader()
on its own never worked either
c
Right, that did not work for me either. Using the plugin action class as contextLoader at the root of the Compose hierarchy did (or the Dialog class in the case of the IDEA plugin example).