From 89561dbc99b60406ec749e61557607e89fe029f9 Mon Sep 17 00:00:00 2001 From: Kirill Grouchnikov Date: Fri, 3 Nov 2023 17:00:44 -0400 Subject: [PATCH] Wire action / popup activation on command buttons via key tips For #56 --- .../aurora/component/AuroraCommandButton.kt | 144 ++++++++++-------- .../component/ribbon/RibbonMetaComponent.kt | 2 + .../component/ribbon/impl/KeyTipTracker.kt | 8 + .../window/ribbon/RibbonTaskToggleButton.kt | 8 + 4 files changed, 96 insertions(+), 66 deletions(-) diff --git a/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/AuroraCommandButton.kt b/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/AuroraCommandButton.kt index bad2f0ed..429e5ebc 100644 --- a/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/AuroraCommandButton.kt +++ b/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/AuroraCommandButton.kt @@ -883,6 +883,65 @@ internal fun Unit = { + val isShowingPopupFromHere = AuroraPopupManager.isShowingPopupFrom( + originator = popupOriginator, + pointInOriginator = AuroraOffset( + x = buttonTopLeftOffset.x + popupAreaOffset.x + popupAreaSize.value.width / 2.0f, + y = buttonTopLeftOffset.y + popupAreaOffset.y + popupAreaSize.value.height / 2.0f + ).asOffset(density) + ) + if (!isShowingPopupFromHere) { + // Display our popup content. + val popupWindow = popupHandler.showPopupContent( + popupOriginator = popupOriginator, + layoutDirection = layoutDirection, + density = density, + textStyle = resolvedTextStyle, + fontFamilyResolver = fontFamilyResolver, + skinColors = skinColors, + colorSchemeBundle = presentationModel.colorSchemeBundle, + skinPainters = painters, + decorationAreaType = decorationAreaType, + compositionLocalContext = compositionLocalContext, + anchorBoundsInWindow = Rect( + offset = buttonTopLeftOffset.asOffset(density), + size = buttonSize.value.asSize(density) + ), + popupTriggerAreaInWindow = Rect( + offset = AuroraOffset( + x = buttonTopLeftOffset.x + popupAreaOffset.x, + y = buttonTopLeftOffset.y + popupAreaOffset.y + ).asOffset(density), + size = popupAreaSize.value.asSize(density) + ), + contentModel = secondaryContentModel, + presentationModel = presentationModel.popupMenuPresentationModel as P, + displayPrototypeCommand = null, + toDismissPopupsOnActivation = presentationModel.toDismissPopupsOnActivation, + popupPlacementStrategy = presentationModel.popupPlacementStrategy, + popupAnchorBoundsProvider = presentationModel.popupAnchorBoundsProvider, + overlays = secondaryOverlays, + popupKind = AuroraPopupManager.PopupKind.Popup + ) + coroutineScope.launch { + popupWindow?.opacity = 1.0f + } + } else { + // Showing a popup that originates from the popup area of this command button. + // Hide it. + AuroraPopupManager.hidePopups(originator = popupOriginator) + } + } + Layout( modifier = modifier.commandButtonLocator( originalProjection, @@ -893,7 +952,7 @@ internal fun Any KeyTipTracker.trackKeyTipOffset( originalProjection, presentationModel.actionKeyTip!!, @@ -1619,8 +1620,13 @@ internal fun Any?, + val popupKeyTipTraversal: Any?, ) : OnGloballyPositionedModifier { override fun onGloballyPositioned(coordinates: LayoutCoordinates) { @@ -2123,7 +2135,7 @@ private class CommandButtonLocator( command.isActionEnabled, bounds, keyTipChainRoot, - keyTipTraversal + null ) } if (presentationModel.popupKeyTip != null) { @@ -2133,7 +2145,7 @@ private class CommandButtonLocator( command.isSecondaryEnabled, bounds, keyTipChainRoot, - keyTipTraversal + popupKeyTipTraversal ) } } @@ -2151,7 +2163,7 @@ private fun Modifier.commandButtonLocator( trackBounds: Boolean, trackKeyTips: Boolean, keyTipChainRoot: Any?, - keyTipTraversal: () -> Any?, + popupKeyTipTraversal: Any?, ) = this.then( CommandButtonLocator( originalProjection, @@ -2162,6 +2174,6 @@ private fun Modifier.commandButtonLocator( trackBounds, trackKeyTips, keyTipChainRoot, - keyTipTraversal + popupKeyTipTraversal ) ) diff --git a/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/ribbon/RibbonMetaComponent.kt b/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/ribbon/RibbonMetaComponent.kt index 63133368..7569af19 100644 --- a/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/ribbon/RibbonMetaComponent.kt +++ b/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/ribbon/RibbonMetaComponent.kt @@ -322,6 +322,7 @@ internal fun RibbonMetaComponent( row = bandRow, rowHeight = bandRowHeight ), + null, keyTipChainRoot, null ) @@ -350,6 +351,7 @@ internal fun RibbonMetaComponent( row = bandRow, rowHeight = bandRowHeight ), + null, keyTipChainRoot, null ) diff --git a/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/ribbon/impl/KeyTipTracker.kt b/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/ribbon/impl/KeyTipTracker.kt index 2e4bbad0..182da41c 100644 --- a/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/ribbon/impl/KeyTipTracker.kt +++ b/component/src/desktopMain/kotlin/org/pushingpixels/aurora/component/ribbon/impl/KeyTipTracker.kt @@ -58,6 +58,7 @@ object KeyTipTracker { val isEnabled: Boolean, var screenRect: AuroraRect, var anchor: Offset, + var onActivated: (() -> Unit)?, val chainRoot: Any?, val traversal: Any? ) @@ -94,6 +95,7 @@ object KeyTipTracker { isEnabled = isEnabled, screenRect = screenRect, anchor = Offset.Zero, + onActivated = null, chainRoot = chainRoot, traversal = traversal, ) @@ -106,6 +108,7 @@ object KeyTipTracker { keyTip: String, isEnabled: Boolean, anchor: Offset, + onActivated: (() -> Unit)?, chainRoot: Any?, traversal: Any?, ) { @@ -114,6 +117,7 @@ object KeyTipTracker { } if (existing != null) { existing.anchor = anchor.copy() + existing.onActivated = onActivated } else { keyTips.add( KeyTipLink( @@ -122,6 +126,7 @@ object KeyTipTracker { isEnabled = isEnabled, screenRect = AuroraRect(0.0f, 0.0f, 0.0f, 0.0f), anchor = anchor.copy(), + onActivated = onActivated, chainRoot = chainRoot, traversal = traversal, ) @@ -164,6 +169,7 @@ object KeyTipTracker { chainRoots.clear() visibleFlow.value = false chainDepth.value = 0 + println("Cleared all key tips, depth ${chainDepth.value}") } fun showRootKeyTipChain(ribbon: Ribbon) { @@ -177,6 +183,7 @@ object KeyTipTracker { if (!isShowingKeyTips()) { return } + println("Processing $char at depth ${chainDepth.value}") val currChain = getCurrentlyShownKeyTipChain()!! val currChainRoot = chainRoots.last() @@ -187,6 +194,7 @@ object KeyTipTracker { if (char.lowercaseChar() == keyTipString.get(0).lowercaseChar()) { // Match! if (link.isEnabled) { + link.onActivated?.invoke() // TODO - activate the element if (link.traversal != null) { val nextChainRoot = link.traversal diff --git a/window/src/desktopMain/kotlin/org/pushingpixels/aurora/window/ribbon/RibbonTaskToggleButton.kt b/window/src/desktopMain/kotlin/org/pushingpixels/aurora/window/ribbon/RibbonTaskToggleButton.kt index 1905982a..b5a29405 100644 --- a/window/src/desktopMain/kotlin/org/pushingpixels/aurora/window/ribbon/RibbonTaskToggleButton.kt +++ b/window/src/desktopMain/kotlin/org/pushingpixels/aurora/window/ribbon/RibbonTaskToggleButton.kt @@ -43,6 +43,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.resolveDefaults import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.IntSize +import kotlinx.coroutines.launch import org.pushingpixels.aurora.common.* import org.pushingpixels.aurora.component.auroraRichTooltip import org.pushingpixels.aurora.component.model.BaseCommand @@ -258,6 +259,8 @@ internal fun RibbonTaskToggleButton( ) val buttonTopLeftOffset = remember { AuroraOffset(0.0f, 0.0f) } val buttonSize = remember { mutableStateOf(IntSize(0, 0)) } + val coroutineScope = rememberCoroutineScope() + val trackBounds = LocalRibbonTrackBounds.current val keyTipChainRoot = LocalRibbonKeyTipChainRoot.current val trackKeyTips = LocalRibbonTrackKeyTips.current @@ -566,6 +569,11 @@ internal fun RibbonTaskToggleButton( presentationModel.actionKeyTip!!, command.isActionEnabled, layoutManager.getActionKeyTipAnchorCenterPoint(command, presentationModel, layoutInfo), + { + coroutineScope.launch { + command.action?.invoke() + } + }, keyTipChainRoot, command.tag )