@@ -5,28 +5,24 @@ import androidx.compose.foundation.layout.*
55import androidx.compose.material3.Text
66import androidx.compose.runtime.Composable
77import androidx.compose.runtime.CompositionLocalProvider
8- import androidx.compose.runtime.LaunchedEffect
8+ import androidx.compose.runtime.DisposableEffect
99import androidx.compose.runtime.compositionLocalOf
1010import androidx.compose.runtime.remember
1111import androidx.compose.ui.Alignment
1212import androidx.compose.ui.Modifier
13- import androidx.compose.ui.awt.ComposePanel
1413import androidx.compose.ui.awt.ComposeWindow
1514import androidx.compose.ui.graphics.Color
1615import androidx.compose.ui.unit.DpSize
1716import androidx.compose.ui.unit.dp
1817import androidx.compose.ui.window.Window
19- import androidx.compose.ui.window.WindowPlacement
2018import androidx.compose.ui.window.WindowPosition
2119import androidx.compose.ui.window.application
2220import androidx.compose.ui.window.rememberWindowState
2321import com.formdev.flatlaf.util.SystemInfo
2422import java.awt.Dimension
2523
26- import java.awt.event.KeyAdapter
27- import java.awt.event.KeyEvent
2824import javax.swing.JFrame
29- import javax.swing.UIManager
25+ import kotlin.reflect.KClass
3026
3127val LocalWindow = compositionLocalOf<JFrame > { error(" No Window Set" ) }
3228
@@ -48,6 +44,8 @@ val LocalWindow = compositionLocalOf<JFrame> { error("No Window Set") }
4844 * @param size The desired size of the window. If null, the window will use its default size.
4945 * @param minSize The minimum size of the window. If null, no minimum size is set.
5046 * @param maxSize The maximum size of the window. If null, no maximum size is set.
47+ * @param unique An optional unique identifier for the window to prevent duplicates.
48+ * @param onClose A lambda function to be called when the window is requested to close.
5149 * @param fullWindowContent If true, the content will extend into the title bar area on macOS.
5250 * @param content The composable content to be displayed in the window.
5351 */
@@ -56,6 +54,7 @@ class PDESwingWindow(
5654 size : Dimension ? = null ,
5755 minSize : Dimension ? = null ,
5856 maxSize : Dimension ? = null ,
57+ unique : KClass <* >? = null ,
5958 fullWindowContent : Boolean = false ,
6059 onClose : () -> Unit = {},
6160 content : @Composable () -> Unit
@@ -75,7 +74,13 @@ class PDESwingWindow(
7574 }
7675 setLocationRelativeTo(null )
7776 setContent {
78- PDEWindowContent (window, titleKey, fullWindowContent, content)
77+ PDEWindowContent (
78+ window = window,
79+ titleKey = titleKey,
80+ unique = unique,
81+ fullWindowContent = fullWindowContent,
82+ content = content
83+ )
7984 }
8085 window.addWindowStateListener {
8186 if (it.newState == JFrame .DISPOSE_ON_CLOSE ){
@@ -87,19 +92,23 @@ class PDESwingWindow(
8792 }
8893}
8994
95+ private val windows = mutableMapOf<KClass <* >, ComposeWindow > ()
96+
9097/* *
9198 * Internal Composable function to set up the window content with theming and localization.
9299 * It also handles macOS specific properties for full window content.
93100 *
94101 * @param window The JFrame instance to be configured.
95102 * @param titleKey The key for the window title, which will be localized.
103+ * @param unique An optional unique identifier for the window to prevent duplicates.
96104 * @param fullWindowContent If true, the content will extend into the title bar area on macOS.
97105 * @param content The composable content to be displayed in the window.
98106 */
99107@Composable
100108private fun PDEWindowContent (
101109 window : ComposeWindow ,
102110 titleKey : String ,
111+ unique : KClass <* >? = null,
103112 fullWindowContent : Boolean = false,
104113 content : @Composable () -> Unit
105114){
@@ -108,6 +117,20 @@ private fun PDEWindowContent(
108117 window.rootPane.putClientProperty(" apple.awt.fullWindowContent" , mac && fullWindowContent)
109118 window.rootPane.putClientProperty(" apple.awt.transparentTitleBar" , mac && fullWindowContent)
110119 }
120+ if (unique != null && windows.contains(unique) && windows[unique] != null ){
121+ windows[unique]?.toFront()
122+ window.dispose()
123+ return
124+ }
125+
126+ DisposableEffect (unique){
127+ unique?.let {
128+ windows[it] = window
129+ }
130+ onDispose {
131+ windows.remove(unique)
132+ }
133+ }
111134
112135 CompositionLocalProvider (LocalWindow provides window) {
113136 PDETheme {
@@ -148,20 +171,18 @@ private fun PDEWindowContent(
148171 * fullscreen if it contains any of [fillMaxWidth]/[fillMaxSize]/[fillMaxHeight] etc.
149172 * @param minSize The minimum size of the window. Defaults to unspecified size which means no minimum size is set.
150173 * @param maxSize The maximum size of the window. Defaults to unspecified size which means no maximum size is set.
151- * @param fullWindowContent If true, the content will extend into the title bar area on
152- * macOS.
174+ * @param unique An optional unique identifier for the window to prevent duplicates.
175+ * @param fullWindowContent If true, the content will extend into the title bar area on macOS.
153176 * @param onClose A lambda function to be called when the window is requested to close.
154177 * @param content The composable content to be displayed in the window.
155- *
156- *
157- *
158178 */
159179@Composable
160180fun PDEComposeWindow (
161181 titleKey : String ,
162182 size : DpSize = DpSize .Unspecified ,
163183 minSize : DpSize = DpSize .Unspecified ,
164184 maxSize : DpSize = DpSize .Unspecified ,
185+ unique : KClass <* >? = null,
165186 fullWindowContent : Boolean = false,
166187 onClose : () -> Unit = {},
167188 content : @Composable () -> Unit
@@ -175,7 +196,13 @@ fun PDEComposeWindow(
175196 window.minimumSize = minSize.toDimension()
176197 window.maximumSize = maxSize.toDimension()
177198 }
178- PDEWindowContent (window, titleKey, fullWindowContent, content)
199+ PDEWindowContent (
200+ window = window,
201+ titleKey = titleKey,
202+ unique = unique,
203+ fullWindowContent = fullWindowContent,
204+ content = content
205+ )
179206 }
180207}
181208
0 commit comments