rob42
07/23/2024, 3:27 PMDialogWindow
🙂
I'd love to see more desktop-native capabilities in Compose Desktop, as well as non-material styled components -- might start to give some other desktop UI toolkits a run for their money if this stuff became easy to domohamed rejeb
07/23/2024, 3:35 PMAlex Styl
07/23/2024, 8:14 PMrob42
07/24/2024, 8:33 AMrob42
07/24/2024, 8:40 AM[NSPopover showRelativeToRect:ofView:preferredEdge]
2. A custom Popup implementation that puts its content inside a borderless DialogWindow, and aligns the window based on the PopupPositionProvider
3. A lot of finessing focus, ensuring the dialog is focused when open and closes if it loses focusrob42
07/24/2024, 9:35 AMandrew
08/07/2024, 8:47 PMzt
08/15/2024, 7:19 PMrob42
08/20/2024, 2:13 PMcalculatePosition(
anchorBounds = IntRect(offset = CURSOR_POS, size = IntSize(1,1)),
windowSize = USABLE_SCREEN_SIZE,
layoutDirection = LocalLayoutDirection.current,
popupContentSize: CONTENT_SIZE,
)
rob42
08/20/2024, 2:15 PMval state = rememberDialogState(size = DpSize.Unspecified)
val density = LocalDensity.current
val layoutDirection = LocalLayoutDirection.current
// Currently this is "one shot", but could be adapted to use a listener on the Window if it was
// necessary to get an updating value.
val usableScreenBounds = remember(parentWindow) { DisplayUtil.getUsableScreenBounds(parentWindow) }
remember(state.size, usableScreenBounds, anchorBoundsInScreen, popupPositionProvider) {
// Wait for measurement before placing and making visible
if (state.size == DpSize.Unspecified) return@remember
state.position = with(density) {
val origin = calculateBoundsRelativeToUsableScreen(
usableScreenBounds = usableScreenBounds,
anchorBoundsInScreen = anchorBoundsInScreen,
contentSize = state.size.roundToPx(density),
popupPositionProvider = popupPositionProvider,
layoutDirection = layoutDirection
).translate(usableScreenBounds.topLeft).topLeft
WindowPosition(
x = origin.x.toDp(),
y = origin.y.toDp(),
)
}
}
DialogWindow(state = state, visible = state.size.isSpecified, ... )
rob42
08/20/2024, 2:15 PMprivate fun calculateBoundsRelativeToUsableScreen(
usableScreenBounds: IntRect,
anchorBoundsInScreen: IntRect,
contentSize: IntSize,
popupPositionProvider: PopupPositionProvider,
layoutDirection: LayoutDirection,
) : IntRect {
// Because PopoverPositionProvider takes a *size* for windowSize (really screen size, in our case),
// coordinates need to be translated to/from a zero-origin rect before and after, to account for any top/left
// insets in the usable screen bounds.
val anchorBoundsRelativeToUsableScreen = anchorBoundsInScreen.translate(-usableScreenBounds.topLeft)
val boundsRelativeToUsableScreen = popupPositionProvider.calculatePosition(
anchorBounds = anchorBoundsRelativeToUsableScreen,
windowSize = usableScreenBounds.size,
layoutDirection = layoutDirection,
popupContentSize = contentSize
).let { IntRect(it, contentSize) }
return boundsRelativeToUsableScreen
}