Strange bug when using ComposePanel in ToolWindowFactory

Answered

Strange bug while using `ComposePanel` inside a ToolWindow Tab. When the ComposePanel is shown there is an empty window shown in the left side of the Project window. Also the `ComposePanel` state is completely lost every time I switch between tabs.
See Video https://www.youtube.com/watch?v=9x3vB_FEAG4

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.ComposePanel
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ToolWindowFactory
import com.intellij.ui.content.ContentFactory
import com.intellij.ui.content.ContentManager
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.awt.Font
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.border.EmptyBorder

class MyToolWindowFactory : ToolWindowFactory {
private lateinit var contentFactory: ContentFactory
private lateinit var contentManager: ContentManager

override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
contentFactory = ContentFactory.SERVICE.getInstance()
contentManager = toolWindow.contentManager

addComposePanel()
addSwingPanel()
}

private fun addSwingPanel() {
val jLabel = JLabel("Swing Panel").apply {
foreground = java.awt.Color.BLACK
font = Font("Default", Font.PLAIN, 20)
border = EmptyBorder(32, 0, 0, 0)
}
val swingPanel = JPanel().apply {
background = java.awt.Color.GREEN
add(jLabel)
}
var index = 0
GlobalScope.launch {
repeat(100) {
jLabel.text = "Swing counter: ${index++}"
delay(1000)
}
}
val swingTab = contentFactory.createContent(swingPanel, "Swing", false)
swingTab.isCloseable = false
contentManager.addContent(swingTab)
}

private fun addComposePanel() {
val composePanel = ComposePanel().apply {
setContent {
var counter by rememberSaveable(Unit) { mutableStateOf(0) }
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Yellow)
) {
Text(
text = "Compose counter: $counter",
fontSize = 20.sp,
modifier = Modifier.padding(32.dp)
)
}

LaunchedEffect(Unit) {
repeat(100) {
delay(1000)
counter += 1
}
}
}
}
val composeTab = contentFactory.createContent(composePanel, "Compose", false)
composeTab.isCloseable = false
contentManager.addContent(composeTab)
}
}
4 comments
Comment actions Permalink

We currently do not support Compose for Desktop in IntelliJ Platform plugins officially. Please use default or IJ Platform specific bundled Swing components and Kotlin UI DSL for forms.

0
Comment actions Permalink

It actually works fine, it's just this bug which I encountered and the state not being preserved. I find it much better than Swing even in the current state.

Yann Cebron Do You mean to say that if I submit a plugin which is using Compose it will not be accepted or it's just not supported officially but still fine to use?

0
Comment actions Permalink

It's fine to use Compose in your plugin and we'll publish it, but we currently offer no support/guidance.

1
Comment actions Permalink

You could create a ticket in https://github.com/JetBrains/compose-jb/issues . If it turns out to be a Compose issue, we will try to fix it 

1

Please sign in to leave a comment.