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