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.compose.ui.modifier
18
19 import androidx.compose.runtime.Stable
20
21 /**
22 * [ModifierLocal]s provide a means of inter-modifier communication. When a modifier provides a
23 * [ModifierLocal], it is available to modifiers on the right of the providing modifier for the
24 * current layout node. The provided [ModifierLocal]s are also available to layout nodes that are
25 * children of the current layout node.
26 *
27 * One must create a [ModifierLocal] instance, which can be referenced by consumers statically.
28 * [ModifierLocal] instances themselves hold no data, and can be thought of as a type-safe
29 * identifier for the data being passed to other modifiers to the right of the providing modifier or
30 * down the tree. [ModifierLocal] factory functions take a single parameter: a factory to create a
31 * default value in cases where a [ModifierLocal] is used without a Provider. If this is a situation
32 * you would rather not handle, you can throw an error in this factory.
33 *
34 * To add a value that can be accessed by other modifiers, create an instance of a
35 * [ProvidableModifierLocal] and add it to the tree by using a [modifierLocalProvider]. Now other
36 * modifiers can access the provided value by using a [modifierLocalConsumer].
37 *
38 * @see ProvidableModifierLocal
39 * @see modifierLocalOf
40 * @see modifierLocalProvider
41 * @see modifierLocalConsumer
42 */
43 @Stable sealed class ModifierLocal<T> constructor(internal val defaultFactory: () -> T)
44
45 /**
46 * [ProvidableModifierLocal]s are [ModifierLocal]s that can be used to provide values using a
47 * [ModifierLocalProvider].
48 *
49 * When you create an instance of a [ProvidableModifierLocal], and want to prevent users of your
50 * library from providing new values but want to allow the values to be consumed, expose a
51 * [ModifierLocal] instead.
52 *
53 * @see ModifierLocal
54 * @see modifierLocalOf
55 * @see modifierLocalProvider
56 * @see modifierLocalConsumer
57 */
58 @Stable
59 class ProvidableModifierLocal<T>(defaultFactory: () -> T) : ModifierLocal<T>(defaultFactory)
60
61 /**
62 * Creates a [ProvidableModifierLocal] and specifies a default factory.
63 *
64 * @param defaultFactory a factory to create a default value in cases where a [ModifierLocal] is
65 * consumed without a Provider. If this is a situation you would rather not handle, you can throw
66 * an error in this factory.
67 *
68 * Here are examples where a modifier can communicate with another in the same modifier chain:
69 *
70 * Sample 1: Modifier sending a message to another to its right.
71 *
72 * @sample androidx.compose.ui.samples.ModifierLocalParentChildCommunicationWithinLayoutNodeSample
73 *
74 * Sample 2: Modifier sending a message to another to its left.
75 *
76 * @sample androidx.compose.ui.samples.ModifierLocalChildParentCommunicationWithinLayoutNodeSample
77 *
78 * Here are examples where a modifier can communicate with another across layout nodes:
79 *
80 * Sample 1: Modifier sending a message to a modifier on a child layout node.
81 *
82 * @sample androidx.compose.ui.samples.ModifierLocalParentChildCommunicationInterLayoutNodeSample
83 *
84 * Sample 2: Modifier sending a message to a modifier on a parent layout node.
85 *
86 * @sample androidx.compose.ui.samples.ModifierLocalChildParentCommunicationInterLayoutNodeSample
87 * @see ProvidableModifierLocal
88 * @see ModifierLocal
89 * @see modifierLocalProvider
90 * @see modifierLocalConsumer
91 */
modifierLocalOfnull92 fun <T> modifierLocalOf(defaultFactory: () -> T): ProvidableModifierLocal<T> =
93 ProvidableModifierLocal(defaultFactory)
94
95 /**
96 * This scope gives us access to modifier locals that are provided by other modifiers to the left of
97 * this modifier, or above this modifier in the layout tree.
98 *
99 * @see modifierLocalOf
100 */
101 interface ModifierLocalReadScope {
102 /**
103 * Read a [ModifierLocal] that was provided by other modifiers to the left of this modifier, or
104 * above this modifier in the layout tree.
105 */
106 val <T> ModifierLocal<T>.current: T
107 }
108