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