Skip to content

Commit 28b225e

Browse files
dmyudintellij-monorepo-bot
authored andcommitted
misc [jewel] Add Modifier.resizeHostOnContentSizeChange
GitOrigin-RevId: a6dbd6ebf76d1284527e48809e8f8cb731c2869c
1 parent 5bb0537 commit 28b225e

3 files changed

Lines changed: 72 additions & 0 deletions

File tree

platform/jewel/ide-laf-bridge/api-dump-experimental.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ f:org.jetbrains.jewel.bridge.JewelComposePanelWrapperKt
1313
- *bs:composeWithoutTheme$default(kotlin.jvm.functions.Function1,kotlin.jvm.functions.Function2,I,java.lang.Object):javax.swing.JComponent
1414
- *bs:composeWithoutTheme$default(Z,kotlin.jvm.functions.Function1,kotlin.jvm.functions.Function2,I,java.lang.Object):javax.swing.JComponent
1515
- *sf:getLocalComponent():androidx.compose.runtime.ProvidableCompositionLocal
16+
f:org.jetbrains.jewel.bridge.component.HostPopupResizeKt
17+
- *sf:resizeHostOnContentSizeChange(androidx.compose.ui.Modifier,kotlin.jvm.functions.Function0,kotlin.jvm.functions.Function1,androidx.compose.runtime.Composer,I,I):androidx.compose.ui.Modifier
1618
f:org.jetbrains.jewel.bridge.theme.IntUiBridgeTextKt
1719
- *sf:retrieveDefaultTextStyle(F):androidx.compose.ui.text.TextStyle
1820
f:org.jetbrains.jewel.bridge.theme.SwingBridgeThemeKt

platform/jewel/ide-laf-bridge/api-dump.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ f:org.jetbrains.jewel.bridge.code.highlighting.CodeHighlighterFactory
9696
- f:createHighlighter():org.jetbrains.jewel.foundation.code.highlighting.CodeHighlighter
9797
f:org.jetbrains.jewel.bridge.code.highlighting.CodeHighlighterFactory$Companion
9898
- f:getInstance(com.intellij.openapi.project.Project):org.jetbrains.jewel.bridge.code.highlighting.CodeHighlighterFactory
99+
f:org.jetbrains.jewel.bridge.component.HostPopupResizeKt
99100
f:org.jetbrains.jewel.bridge.icon.IntelliJIconKeyKt
100101
- sf:fromPlatformIcon(org.jetbrains.jewel.ui.icon.IntelliJIconKey$Companion,javax.swing.Icon,java.lang.Class):org.jetbrains.jewel.ui.icon.IconKey
101102
- bs:fromPlatformIcon$default(org.jetbrains.jewel.ui.icon.IntelliJIconKey$Companion,javax.swing.Icon,java.lang.Class,I,java.lang.Object):org.jetbrains.jewel.ui.icon.IconKey
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2+
package org.jetbrains.jewel.bridge.component
3+
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.remember
6+
import androidx.compose.ui.Modifier
7+
import androidx.compose.ui.layout.layout
8+
import androidx.compose.ui.unit.Constraints
9+
import com.intellij.openapi.ui.popup.JBPopup
10+
import com.intellij.ui.scale.JBUIScale
11+
import java.awt.Dimension
12+
import javax.swing.SwingUtilities
13+
import org.jetbrains.annotations.ApiStatus
14+
import org.jetbrains.jewel.foundation.ExperimentalJewelApi
15+
import org.jetbrains.jewel.foundation.LocalComponent
16+
17+
/**
18+
* Keeps the hosting `JewelComposePanel` and its [JBPopup] sized to fit the Compose content. To keep a dimension fixed,
19+
* constrain it in the modifier chain (e.g. `.width(450.dp)`); unconstrained dimensions grow with the content.
20+
*
21+
* Example:
22+
* ```kotlin
23+
* Column(
24+
* modifier = Modifier
25+
* .resizeHostOnContentSizeChange(popup = { popupRef })
26+
* .width(450.dp)
27+
* ) { ... }
28+
* ```
29+
*
30+
* @param popup the popup hosting the panel; its `size` is kept in sync with the content. Invoked lazily so the modifier
31+
* can be created before the popup reference is assigned.
32+
* @param onResize runs on the EDT after the resize is applied, e.g. for popup repositioning.
33+
*/
34+
@ApiStatus.Experimental
35+
@ExperimentalJewelApi
36+
@Composable
37+
public fun Modifier.resizeHostOnContentSizeChange(popup: () -> JBPopup?, onResize: (Dimension) -> Unit = {}): Modifier {
38+
val host = LocalComponent.current
39+
val lastDp = remember { intArrayOf(-1, -1) }
40+
return this.layout { measurable, constraints ->
41+
val relaxed =
42+
constraints.copy(
43+
minWidth = 0,
44+
maxWidth = Constraints.Infinity,
45+
minHeight = 0,
46+
maxHeight = Constraints.Infinity,
47+
)
48+
val placeable = measurable.measure(relaxed)
49+
val scale = JBUIScale.sysScale(host)
50+
val widthDp = (placeable.width / scale).toInt()
51+
val heightDp = (placeable.height / scale).toInt()
52+
if (widthDp != lastDp[0] || heightDp != lastDp[1]) {
53+
lastDp[0] = widthDp
54+
lastDp[1] = heightDp
55+
val newSize = Dimension(widthDp, heightDp)
56+
SwingUtilities.invokeLater {
57+
host.preferredSize = newSize
58+
popup()?.size = newSize
59+
onResize(newSize)
60+
}
61+
}
62+
layout(
63+
placeable.width.coerceIn(constraints.minWidth, constraints.maxWidth),
64+
placeable.height.coerceIn(constraints.minHeight, constraints.maxHeight),
65+
) {
66+
placeable.placeRelative(0, 0)
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)