In this tutorial, we'll show you how to make the `Swing/Compose` interop work in your application, what its limitations are, what you can achieve with it, in which cases you may use it and when you shouldn't do that.
The main goals of the interoperability between Compose Multiplatform and Swing are
- make it easier and smoother to migrate Swing applications to to Compose
- allow to enhance Compose application with Swing components that don't have 'Compose' analogues
In many cases it is more efficient to implement a missing Component in Compose (and contribute it to community) rather than using a Swing component in a Compose Application.
## Swing interop use cases and limitations
Before combining Compose Multiplatform and Swing, it's important to keep in mind that these two technologies have different approaches to the content rendering. Compose Multiplatform uses one heavyweight Swing component to render all its content and has logical rendering layers, while Swing operates on both heavyweight and lightweight components (`Component/JComponent`). For Swing logic Compose Multiplatform is just one more heavyweight component and it interacts with it the same way as with all other Swing components.
The first use-case is addition of a Compose part into a Swing application. It could be done use `ComposePanel` Swing component to render the "Compose" part of the application. From Swing perspective it will be just another Swing component, that should be treated accordingly. Important point, that all Compose components will be rendered inside the `ComposePanel`, including popups, tooltips, context menus, etc. They will be positioned and resized inside the `ComposePanel`. So probably it would be better to replace them with a Swing based implementation.
Below you can find several cases where the use of `ComposePanel` is justified:
- you want to embed animated objects or a whole panel of animated objects into your application (selection of emoticons, toolbar with animated reaction to events, etc.)
- you want to implement an interactive rendering area in your application, which is easier and more convenient to implement using Compose (for example, any type of graphics or infographics)
- you want to embed a complex rendering area (perhaps even animated) into your application - this is easier and more convenient to do using Compose
- you want to replace complex parts of the user interface of your Swing-based application - Compose has a convenient component layout system, and Compose offers a wide range of built-in components and options for quickly creating your own components
If your case is somewhat similar to one of the above, then you should try to implement it using `ComposePanel`.
The second use case is situation when you want to use some component, that exists in Swing and there is no analogue in Compose. And creating it from scratch is too expensive. In this case, you can use `SwingPanel`. A `SwingPanel` is a wrapper that controls the size, position and rendering of a Swing component that is placed on top of a Compose Multiplatform component, meaning the component inside a `SwingPanel` will always be on top of the Compose in depth. Anything that is misplaced and rests on the `SwingPanel` will be clipped by the Swing component placed there, so try to think about these situations, and if there is such a risk, then it is better to either redesign the UI accordingly, or stop using the `SwingPanel` and still try to implement the missing component, thereby contributing to the development of technology and making life easier for other developers.
Below you can find several cases where the use of `SwingPanel` is justified:
- there are no popups, tooltips, context menus, etc. in your application. or they are not used inside your `SwingPanel`
- in your application, the `SwingPanel` will always be in the same position. This will reduce the risk of glitches and artifacts when changing the position of the Swing component (this condition is not mandatory and you need to test each such case separately)
If your case is somewhat similar to one of the above, then you should try to implement it using `SwingPanel`.
Since Compose Multiplatform and Swing can be combined in both directions, it is quite possible to place a `SwingPanel` into a `ComposePanel`, which in turn could be placed into another `SwingPanel`. In this case, you should be careful to minimize rendering glitches. At the end of this tutorial, you can find an example covering this case.
`ComposePanel` lets you create a UI using Compose Multiplatform in a Swing-based UI. To achieve this you need to create an instance of `ComposePanel`, add it to your Swing layout, and describe the composition inside `setContent`.
SwingPanel lets you create a UI using Swing in a Compose-based UI. To achieve this you need to create Swing `JComponent` in the `factory` parameter of `SwingPanel`.
## Updating Swing component when Сompose state changes
Example below shows how to update a Swing component in a `SwingPanel` when the composable state changes. To do this, you need to provide an `update: (T) -> Unit` callback that is called when the composable state changes or after the layout is inflated.
Example below shows how Compose for Desktop and Swing can be combined in both directions i.e. adding a `SwingPanel` to a `ComposePanel` which is in turn added to another `SwingPanel`.