1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.glance.layout
18 
19 import androidx.annotation.RestrictTo
20 import androidx.compose.runtime.Composable
21 import androidx.glance.Emittable
22 import androidx.glance.EmittableWithChildren
23 import androidx.glance.GlanceModifier
24 import androidx.glance.GlanceNode
25 import androidx.glance.unit.Dimension
26 
27 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
28 class EmittableBox : EmittableWithChildren() {
29     override var modifier: GlanceModifier = GlanceModifier
30     var contentAlignment: Alignment = Alignment.TopStart
31 
copynull32     override fun copy(): Emittable =
33         EmittableBox().also {
34             it.modifier = modifier
35             it.contentAlignment = contentAlignment
36             it.children.addAll(children.map { it.copy() })
37         }
38 
toStringnull39     override fun toString(): String =
40         "EmittableBox(" +
41             "modifier=$modifier, " +
42             "contentAlignment=$contentAlignment" +
43             "children=[\n${childrenToString()}\n]" +
44             ")"
45 }
46 
47 /**
48  * A layout composable with [content].
49  *
50  * By default, the [Box] will size itself to fit the content, unless a [Dimension] constraint has
51  * been provided. When the children are smaller than the [Box], they will be placed within the box
52  * subject to the [contentAlignment]. When the [content] has more than one layout child, all of the
53  * children will be stacked on top of each other in the composition order.
54  *
55  * Note for App Widgets: [Box] supports up to 10 child elements. Any additional elements will be
56  * truncated from the output.
57  *
58  * @param modifier The modifier to be applied to the layout.
59  * @param contentAlignment The alignment of children within the [Box].
60  * @param content The content inside the [Box].
61  */
62 @Composable
63 fun Box(
64     modifier: GlanceModifier = GlanceModifier,
65     contentAlignment: Alignment = Alignment.TopStart,
66     content: @Composable () -> Unit
67 ) {
68     GlanceNode(
69         factory = ::EmittableBox,
70         update = {
71             this.set(modifier) { this.modifier = it }
72             this.set(contentAlignment) { this.contentAlignment = it }
73         },
74         content = content
75     )
76 }
77