1 /*
<lambda>null2  * 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.compose.runtime
18 
19 /**
20  * Convert a lambda into one that moves the remembered state and nodes created in a previous call to
21  * the new location it is called.
22  *
23  * Tracking compositions can be used to produce a composable that moves its content between a row
24  * and a column based on a parameter, such as,
25  *
26  * @sample androidx.compose.runtime.samples.MovableContentColumnRowSample
27  *
28  * Or they can be used to ensure the composition state tracks with a model as moves in the layout,
29  * such as,
30  *
31  * @sample androidx.compose.runtime.samples.MovableContentMultiColumnSample
32  * @param content The composable lambda to convert into a state tracking lambda.
33  * @return A tracking composable lambda
34  */
35 @OptIn(InternalComposeApi::class)
36 fun movableContentOf(content: @Composable () -> Unit): @Composable () -> Unit {
37     val movableContent = MovableContent<Nothing?>({ content() })
38     return { currentComposer.insertMovableContent(movableContent, null) }
39 }
40 
41 /**
42  * Convert a lambda into one that moves the remembered state and nodes created in a previous call to
43  * the new location it is called.
44  *
45  * Tracking compositions can be used to produce a composable that moves its content between a row
46  * and a column based on a parameter, such as,
47  *
48  * @sample androidx.compose.runtime.samples.MovableContentColumnRowSample
49  *
50  * Or they can be used to ensure the composition state tracks with a model as moves in the layout,
51  * such as,
52  *
53  * @sample androidx.compose.runtime.samples.MovableContentMultiColumnSample
54  * @param content The composable lambda to convert into a state tracking lambda.
55  * @return A tracking composable lambda
56  */
57 @OptIn(InternalComposeApi::class)
58 fun <P> movableContentOf(content: @Composable (P) -> Unit): @Composable (P) -> Unit {
59     val movableContent = MovableContent(content)
<lambda>null60     return { currentComposer.insertMovableContent(movableContent, it) }
61 }
62 
63 /**
64  * Convert a lambda into one that moves the remembered state and nodes created in a previous call to
65  * the new location it is called.
66  *
67  * Tracking compositions can be used to produce a composable that moves its content between a row
68  * and a column based on a parameter, such as,
69  *
70  * @sample androidx.compose.runtime.samples.MovableContentColumnRowSample
71  *
72  * Or they can be used to ensure the composition state tracks with a model as moves in the layout,
73  * such as,
74  *
75  * @sample androidx.compose.runtime.samples.MovableContentMultiColumnSample
76  * @param content The composable lambda to convert into a state tracking lambda.
77  * @return A tracking composable lambda
78  */
79 @OptIn(InternalComposeApi::class)
80 fun <P1, P2> movableContentOf(content: @Composable (P1, P2) -> Unit): @Composable (P1, P2) -> Unit {
<lambda>null81     val movableContent = MovableContent<Pair<P1, P2>> { content(it.first, it.second) }
p1null82     return { p1, p2 -> currentComposer.insertMovableContent(movableContent, p1 to p2) }
83 }
84 
85 /**
86  * Convert a lambda into one that moves the remembered state and nodes created in a previous call to
87  * the new location it is called.
88  *
89  * Tracking compositions can be used to produce a composable that moves its content between a row
90  * and a column based on a parameter, such as,
91  *
92  * @sample androidx.compose.runtime.samples.MovableContentColumnRowSample
93  *
94  * Or they can be used to ensure the composition state tracks with a model as moves in the layout,
95  * such as,
96  *
97  * @sample androidx.compose.runtime.samples.MovableContentMultiColumnSample
98  * @param content The composable lambda to convert into a state tracking lambda.
99  * @return A tracking composable lambda
100  */
101 @OptIn(InternalComposeApi::class)
102 fun <P1, P2, P3> movableContentOf(
103     content: @Composable (P1, P2, P3) -> Unit
104 ): @Composable (P1, P2, P3) -> Unit {
105     val movableContent =
<lambda>null106         MovableContent<Triple<P1, P2, P3>> { content(it.first, it.second, it.third) }
p1null107     return { p1, p2, p3 ->
108         currentComposer.insertMovableContent(movableContent, Triple(p1, p2, p3))
109     }
110 }
111 
112 /**
113  * Convert a lambda into one that moves the remembered state and nodes created in a previous call to
114  * the new location it is called.
115  *
116  * Tracking compositions can be used to produce a composable that moves its content between a row
117  * and a column based on a parameter, such as,
118  *
119  * @sample androidx.compose.runtime.samples.MovableContentColumnRowSample
120  *
121  * Or they can be used to ensure the composition state tracks with a model as moves in the layout,
122  * such as,
123  *
124  * @sample androidx.compose.runtime.samples.MovableContentMultiColumnSample
125  * @param content The composable lambda to convert into a state tracking lambda.
126  * @return A tracking composable lambda
127  */
128 @OptIn(InternalComposeApi::class)
129 fun <P1, P2, P3, P4> movableContentOf(
130     content: @Composable (P1, P2, P3, P4) -> Unit
131 ): @Composable (P1, P2, P3, P4) -> Unit {
132     val movableContent =
p1null133         MovableContent<Array<Any?>> { (p1, p2, p3, p4) ->
134             @Suppress("UNCHECKED_CAST") // Types are guaranteed below.
135             content(p1 as P1, p2 as P2, p3 as P3, p4 as P4)
136         }
p1null137     return { p1, p2, p3, p4 ->
138         currentComposer.insertMovableContent(movableContent, arrayOf(p1, p2, p3, p4))
139     }
140 }
141 
142 /**
143  * Convert a lambda with a receiver into one that moves the remembered state and nodes created in a
144  * previous call to the new location it is called.
145  *
146  * Tracking compositions can be used to produce a composable that moves its content between a row
147  * and a column based on a parameter, such as,
148  *
149  * @sample androidx.compose.runtime.samples.MovableContentColumnRowSample
150  *
151  * Or they can be used to ensure the composition state tracks with a model as moves in the layout,
152  * such as,
153  *
154  * @sample androidx.compose.runtime.samples.MovableContentMultiColumnSample
155  * @param content The composable lambda to convert into a state tracking lambda.
156  * @return A tracking composable lambda
157  */
158 @OptIn(InternalComposeApi::class)
movableContentWithReceiverOfnull159 fun <R> movableContentWithReceiverOf(content: @Composable R.() -> Unit): @Composable R.() -> Unit {
160     val movableContent = MovableContent<R>({ it.content() })
161     return { currentComposer.insertMovableContent(movableContent, this) }
162 }
163 
164 /**
165  * Convert a lambda with a receiver into one that moves the remembered state and nodes created in a
166  * previous call to the new location it is called.
167  *
168  * Tracking compositions can be used to produce a composable that moves its content between a row
169  * and a column based on a parameter, such as,
170  *
171  * @sample androidx.compose.runtime.samples.MovableContentColumnRowSample
172  *
173  * Or they can be used to ensure the composition state tracks with a model as moves in the layout,
174  * such as,
175  *
176  * @sample androidx.compose.runtime.samples.MovableContentMultiColumnSample
177  * @param content The composable lambda to convert into a state tracking lambda.
178  * @return A tracking composable lambda
179  */
180 @OptIn(InternalComposeApi::class)
movableContentWithReceiverOfnull181 fun <R, P> movableContentWithReceiverOf(
182     content: @Composable R.(P) -> Unit
183 ): @Composable R.(P) -> Unit {
184     val movableContent = MovableContent<Pair<R, P>>({ it.first.content(it.second) })
185     return { currentComposer.insertMovableContent(movableContent, this to it) }
186 }
187 
188 /**
189  * Convert a lambda with a receiver into one that moves the remembered state and nodes created in a
190  * previous call to the new location it is called.
191  *
192  * Tracking compositions can be used to produce a composable that moves its content between a row
193  * and a column based on a parameter, such as,
194  *
195  * @sample androidx.compose.runtime.samples.MovableContentColumnRowSample
196  *
197  * Or they can be used to ensure the composition state tracks with a model as moves in the layout,
198  * such as,
199  *
200  * @sample androidx.compose.runtime.samples.MovableContentMultiColumnSample
201  * @param content The composable lambda to convert into a state tracking lambda.
202  * @return A tracking composable lambda
203  */
204 @OptIn(InternalComposeApi::class)
movableContentWithReceiverOfnull205 fun <R, P1, P2> movableContentWithReceiverOf(
206     content: @Composable R.(P1, P2) -> Unit
207 ): @Composable R.(P1, P2) -> Unit {
208     val movableContent = MovableContent<Triple<R, P1, P2>> { it.first.content(it.second, it.third) }
209     return { p1, p2 -> currentComposer.insertMovableContent(movableContent, Triple(this, p1, p2)) }
210 }
211 
212 /**
213  * Convert a lambda with a receiver into one that moves the remembered state and nodes created in a
214  * previous call to the new location it is called.
215  *
216  * Tracking compositions can be used to produce a composable that moves its content between a row
217  * and a column based on a parameter, such as,
218  *
219  * @sample androidx.compose.runtime.samples.MovableContentColumnRowSample
220  *
221  * Or they can be used to ensure the composition state tracks with a model as moves in the layout,
222  * such as,
223  *
224  * @sample androidx.compose.runtime.samples.MovableContentMultiColumnSample
225  * @param content The composable lambda to convert into a state tracking lambda.
226  * @return A tracking composable lambda
227  */
228 @OptIn(InternalComposeApi::class)
movableContentWithReceiverOfnull229 fun <R, P1, P2, P3> movableContentWithReceiverOf(
230     content: @Composable R.(P1, P2, P3) -> Unit
231 ): @Composable R.(P1, P2, P3) -> Unit {
232     val movableContent =
233         MovableContent<Array<Any?>> { (r, p1, p2, p3) ->
234             @Suppress("UNCHECKED_CAST") // Types are guaranteed below.
235             (r as R).content(p1 as P1, p2 as P2, p3 as P3)
236         }
237     return { p1, p2, p3 ->
238         currentComposer.insertMovableContent(movableContent, arrayOf(this, p1, p2, p3))
239     }
240 }
241 
242 // An arbitrary key created randomly. This key is used for the group containing the movable content
243 internal const val movableContentKey = 0x078cc281
244