[go: nahoru, domu]

blob: f02f4f5d3c64f9ca99d088008a5e657859dc0a12 [file] [log] [blame]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:OptIn(ComposeCompilerApi::class, ExperimentalComposeApi::class)
package androidx.compose
/**
* Emits a node into the composition of type [T].
*
* This function will throw a runtime exception if [E] is not a subtype of the applier of the
* [currentComposer].
*
* @sample androidx.compose.samples.CustomTreeComposition
*
* @param ctor A function which will create a new instance of [T]. This function is NOT
* guaranteed to be called in place.
* @param update A function to perform updates on the node. This will run every time emit is
* executed. This function is called in place and will be inlined.
*
* @see Updater
* @see Applier
* @see emit
* @see compositionFor
*/
@OptIn(ComposeCompilerApi::class)
@Composable inline fun <T : Any, reified E : Applier<*>> emit(
noinline ctor: () -> T,
update: Updater<T>.() -> Unit
) {
require(currentComposer.applier is E)
currentComposer.startNode()
val node = if (currentComposer.inserting)
ctor().also { currentComposer.emitNode(it) }
else
@Suppress("UNCHECKED_CAST")
currentComposer.useNode() as T
Updater(currentComposer, node).update()
currentComposer.endNode()
}
// TODO(lmr): make assert more informative
// TODO(lmr): consider invoking children manually
// TODO(lmr): consider ComposableContract for this
/**
* Emits a node into the composition of type [T]. Nodes emitted inside of [children] will become
* children of the emitted node.
*
* This function will throw a runtime exception if [E] is not a subtype of the applier of the
* [currentComposer].
*
* @sample androidx.compose.samples.CustomTreeComposition
*
* @param ctor A function which will create a new instance of [T]. This function is NOT
* guaranteed to be called in place.
* @param update A function to perform updates on the node. This will run every time emit is
* executed. This function is called in place and will be inlined.
* @param children the composable content that will emit the "children" of this node.
*
* @see Updater
* @see Applier
* @see emit
* @see compositionFor
*/
@OptIn(ComposeCompilerApi::class)
@Composable
inline fun <T : Any?, reified E : Applier<*>> emit(
noinline ctor: () -> T,
update: Updater<T>.() -> Unit,
children: @Composable () -> Unit
) {
if (currentComposer.applier !is E) invalidApplier()
currentComposer.startNode()
val node = if (currentComposer.inserting)
ctor().also { currentComposer.emitNode(it) }
else
@Suppress("UNCHECKED_CAST")
currentComposer.useNode() as T
Updater(currentComposer, node).update()
children()
currentComposer.endNode()
}
@PublishedApi
internal fun invalidApplier(): Nothing = error("Invalid applier")