diff --git a/designcompose/src/main/java/com/android/designcompose/DesignFrame.kt b/designcompose/src/main/java/com/android/designcompose/DesignFrame.kt index cdcf5e020..bad4ae159 100644 --- a/designcompose/src/main/java/com/android/designcompose/DesignFrame.kt +++ b/designcompose/src/main/java/com/android/designcompose/DesignFrame.kt @@ -44,7 +44,6 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp -import com.android.designcompose.serdegen.ComponentInfo import com.android.designcompose.serdegen.GridLayoutType import com.android.designcompose.serdegen.GridSpan import com.android.designcompose.serdegen.ItemSpacing @@ -53,7 +52,6 @@ import com.android.designcompose.serdegen.View import com.android.designcompose.serdegen.ViewData import com.android.designcompose.serdegen.ViewShape import com.android.designcompose.serdegen.ViewStyle -import java.util.Optional @Composable internal fun DesignFrame( @@ -61,13 +59,11 @@ internal fun DesignFrame( view: View, baseVariantView: View?, style: ViewStyle, - variantParentName: String, layoutInfo: SimplifiedLayoutInfo, document: DocContent, customizations: CustomizationContext, parentLayout: ParentLayoutInfo?, layoutId: Int, - componentInfo: Optional, parentComponents: List, maskInfo: MaskInfo?, content: @Composable () -> Unit, @@ -132,17 +128,13 @@ internal fun DesignFrame( } } - // Check to see if this node is part of a component set with variants and if any @DesignVariant - // annotations set variant properties that match. If so, variantNodeName will be set to the - // name of the node with all the variants set to the @DesignVariant parameters - val variantNodeName = customizations.getMatchingVariant(componentInfo) + // Check for a customization that replaces this component completely val replacementComponent = customizations.getComponent(name) var m = Modifier as Modifier - // Only render the frame if we don't have a custom variant node that we are about to - // render instead + // Only render the frame if we don't have a replacement node val shape = (view.data as ViewData.Container).shape - if (variantNodeName.isNullOrEmpty() && replacementComponent == null) + if (replacementComponent == null) m = m.frameRender(style, shape, customImage, document, name, customizations, maskInfo) m = m.then(modifier) val customModifier = customizations.getModifier(name) @@ -169,23 +161,6 @@ internal fun DesignFrame( return true } - // If we a custom variant, compose it instead and then return. - if (variantNodeName != null) { - // Get the generated CustomVariantComponent() function and call it with variantNodeName - val customComposable = customizations.getCustomComposable() - if (customComposable != null) { - val tapCallback = customizations.getTapCallback(name) - customComposable( - layoutInfo.selfModifier.then(m), - variantNodeName, - NodeQuery.NodeVariant(variantNodeName, variantParentName.ifEmpty { name }), - parentComponents, - tapCallback - ) - return true - } - } - val lazyContent = customizations.getListContent(name) // Select the appropriate representation for ourselves based on our layout style; @@ -584,19 +559,18 @@ internal fun DesignFrame( } } is LayoutInfoAbsolute -> { - println("### DesignFrame $name layoutId $layoutId isWidgetChild ${parentLayout?.isWidgetChild}") + println( + "### DesignFrame $name layoutId $layoutId isWidgetChild ${parentLayout?.isWidgetChild}" + ) if (parentLayout?.isWidgetChild == true) { // For direct children of a widget, render the frame as a box with the calculated // layout size, then compose the frame's children with our custom layout val layout = LayoutManager.getLayout(layoutId) Box(m.layoutSizeToModifier(layout)) { - DesignFrameLayout(modifier, name, layoutId, layoutState) { - content() - } + DesignFrameLayout(modifier, name, layoutId, layoutState) { content() } } - } - else { + } else { // Otherwise, use our custom layout to render the frame and to place its children m = m.then(Modifier.layoutStyle(name, layoutId)) DesignFrameLayout(m, name, layoutId, layoutState) { diff --git a/designcompose/src/main/java/com/android/designcompose/DesignView.kt b/designcompose/src/main/java/com/android/designcompose/DesignView.kt index 727ee1967..4a83d6e6f 100644 --- a/designcompose/src/main/java/com/android/designcompose/DesignView.kt +++ b/designcompose/src/main/java/com/android/designcompose/DesignView.kt @@ -78,7 +78,6 @@ import com.android.designcompose.serdegen.Trigger import com.android.designcompose.serdegen.View import com.android.designcompose.serdegen.ViewData import com.android.designcompose.serdegen.ViewStyle -import java.util.Optional import kotlin.math.min import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -358,8 +357,31 @@ internal fun DesignView( } // See if we've got a replacement node from an interaction - val view = interactionState.nodeVariant(v.id, customizations.getKey(), document) ?: v - val hasVariantReplacement = view.name != v.name + var view = interactionState.nodeVariant(v.id, customizations.getKey(), document) ?: v + var hasVariantReplacement = view.name != v.name + var variantParentName = variantParentName + if (!hasVariantReplacement) { + // If an interaction has not changed the current variant, then check to see if this node + // is part of a component set with variants and if any @DesignVariant annotations + // set variant properties that match. If so, variantNodeName will be set to the + // name of the node with all the variants set to the @DesignVariant parameters + var variantNodeName = customizations.getMatchingVariant(view.component_info) + if (variantNodeName != null) { + // Find the view associated with the variant name + val variantNodeQuery = + NodeQuery.NodeVariant(variantNodeName, variantParentName.ifEmpty { view.name }) + val isRoot = LocalDesignIsRootContext.current.isRoot + val variantView = interactionState.rootNode(variantNodeQuery, document, isRoot) + if (variantView != null) { + view = variantView + hasVariantReplacement = true + variantView.component_info.ifPresent { + variantParentName = it.component_set_name + } + } + } + } + var m = Modifier as Modifier // Use the recompose highlighter to show what is being recomposed, if the design switcher @@ -670,17 +692,11 @@ internal fun DesignView( view, if (hasVariantReplacement) v else null, style, - variantParentName, viewLayoutInfo, document, customizations, parentLayout, layoutId, - // Check to see whether an interaction has changed the current variant. If it did, - // then - // we ignore any variant properties set from @DesignVariant annotations by passing - // Optional.empty into DesignFrame's componentInfo parameter. - if (hasVariantReplacement) Optional.empty() else view.component_info, parentComponents, MaskInfo(parentSize, maskViewType), ) { @@ -953,10 +969,11 @@ internal fun DesignDocInternal( CompositionLocalProvider(LocalDesignIsRootContext provides DesignIsRoot(false)) { // Whenever the root view changes, call newDoc() so that we defer layout calculation // until all views have been added - if (isRoot) DisposableEffect(startFrame) { - LayoutManager.newDoc() - onDispose { } - } + if (isRoot) + DisposableEffect(startFrame) { + LayoutManager.newDoc() + onDispose {} + } DesignView( modifier, @@ -999,10 +1016,11 @@ internal fun DesignDocInternal( // For root views, tell the layout manager that it is done loading after all // child composables have been called so that it can trigger a layout compute. - if (isRoot) DisposableEffect(startFrame) { - LayoutManager.docLoaded() - onDispose { } - } + if (isRoot) + DisposableEffect(startFrame) { + LayoutManager.docLoaded() + onDispose {} + } } return diff --git a/designcompose/src/main/java/com/android/designcompose/Layout.kt b/designcompose/src/main/java/com/android/designcompose/Layout.kt index 95d143417..bcad40d17 100644 --- a/designcompose/src/main/java/com/android/designcompose/Layout.kt +++ b/designcompose/src/main/java/com/android/designcompose/Layout.kt @@ -513,8 +513,11 @@ internal fun Modifier.layoutStyle(name: String, layoutId: Int) = this.then(DesignLayoutData(name, layoutId)) internal fun Layout.width() = this.width.roundToInt() + internal fun Layout.height() = this.height.roundToInt() + internal fun Layout.left() = this.left.roundToInt() + internal fun Layout.top() = this.top.roundToInt() // Layout function for DesignFrame @@ -533,10 +536,7 @@ internal inline fun DesignFrameLayout( // Measure policy for DesignFrame. internal fun designMeasurePolicy(name: String, layoutId: Int) = MeasurePolicy { measurables, constraints -> - val placeables = - measurables.map { measurable -> - measurable.measure(constraints) - } + val placeables = measurables.map { measurable -> measurable.measure(constraints) } var myLayout = LayoutManager.getLayout(layoutId) if (myLayout == null) { @@ -559,10 +559,7 @@ internal fun designMeasurePolicy(name: String, layoutId: Int) = if (childLayout == null) { println("### ERROR childLayout NULL layoutId $layoutId") } else { - placeable.place( - x = childLayout.left(), - y = childLayout.top() - ) + placeable.place(x = childLayout.left(), y = childLayout.top()) } } } diff --git a/integration-tests/validation/src/main/java/com/android/designcompose/testapp/validation/MainActivity.kt b/integration-tests/validation/src/main/java/com/android/designcompose/testapp/validation/MainActivity.kt index 2e8882f83..edcb5e8d0 100644 --- a/integration-tests/validation/src/main/java/com/android/designcompose/testapp/validation/MainActivity.kt +++ b/integration-tests/validation/src/main/java/com/android/designcompose/testapp/validation/MainActivity.kt @@ -195,6 +195,10 @@ interface HelloWorld { widgetItems: ListContent, @Design(node = "#Rect1") showRect1: Boolean, @Design(node = "#Rect2") showRect2: Boolean, + @Design(node = "#media/now-playing/skip-prev-button") showPrev: Boolean, + @Design(node = "#media/now-playing/skip-next-button") showNext: Boolean, + @DesignVariant(property = "#media/now-playing/play-state-button") playState: PlayState, + @Design(node = "#media/now-playing/play-state-button") onPlayPauseTap: TapCallback, ) @DesignComponent(node = "#BlueSquare") fun BlueSquare() @DesignComponent(node = "#RedSquare") fun RedSquare() @@ -279,6 +283,12 @@ fun HelloWorld() { }, showRect1 = showRect1, showRect2 = showRect2, + showPrev = false, + showNext = true, + playState = PlayState.Play, + onPlayPauseTap = { + println("### Tap") + }, designComposeCallbacks = DesignComposeCallbacks( docReadyCallback = { id ->