1 /*
2  * Copyright 2023 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  *      https://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 com.google.accompanist.adaptive
18 
19 import androidx.compose.foundation.layout.Column
20 import androidx.compose.foundation.layout.ColumnScope
21 import androidx.compose.foundation.layout.LayoutScopeMarker
22 import androidx.compose.runtime.Immutable
23 import androidx.compose.runtime.Stable
24 import androidx.compose.ui.Alignment
25 import androidx.compose.ui.Modifier
26 import androidx.compose.ui.layout.Measured
27 import androidx.compose.ui.layout.VerticalAlignmentLine
28 import androidx.compose.ui.platform.debugInspectorInfo
29 
30 /**
31  * Copy of [ColumnScope] that excludes the weight Modifier attribute.
32  *
33  * Also adds a new [ignoreFold] Modifier attribute.
34  */
35 @LayoutScopeMarker
36 @Immutable
37 public interface FoldAwareColumnScope {
38     /**
39      * Ignore the fold when placing this child within the [FoldAwareColumn].
40      */
41     @Stable
ignoreFoldnull42     public fun Modifier.ignoreFold(): Modifier
43 
44     /**
45      * Align the element horizontally within the [Column]. This alignment will have priority over
46      * the [Column]'s `horizontalAlignment` parameter.
47      *
48      * Example usage:
49      * @sample androidx.compose.foundation.layout.samples.SimpleAlignInColumn
50      */
51     @Stable
52     public fun Modifier.align(alignment: Alignment.Horizontal): Modifier
53 
54     /**
55      * Position the element horizontally such that its [alignmentLine] aligns with sibling elements
56      * also configured to [alignBy]. [alignBy] is a form of [align],
57      * so both modifiers will not work together if specified for the same layout.
58      * Within a [Column], all components with [alignBy] will align horizontally using
59      * the specified [VerticalAlignmentLine]s or values provided using the other
60      * [alignBy] overload, forming a sibling group.
61      * At least one element of the sibling group will be placed as it had [Alignment.Start] align
62      * in [Column], and the alignment of the other siblings will be then determined such that
63      * the alignment lines coincide. Note that if only one element in a [Column] has the
64      * [alignBy] modifier specified the element will be positioned
65      * as if it had [Alignment.Start] align.
66      *
67      * Example usage:
68      * @sample androidx.compose.foundation.layout.samples.SimpleRelativeToSiblingsInColumn
69      */
70     @Stable
71     public fun Modifier.alignBy(alignmentLine: VerticalAlignmentLine): Modifier
72 
73     /**
74      * Position the element horizontally such that the alignment line for the content as
75      * determined by [alignmentLineBlock] aligns with sibling elements also configured to
76      * [alignBy]. [alignBy] is a form of [align], so both modifiers
77      * will not work together if specified for the same layout.
78      * Within a [Column], all components with [alignBy] will align horizontally using
79      * the specified [VerticalAlignmentLine]s or values obtained from [alignmentLineBlock],
80      * forming a sibling group.
81      * At least one element of the sibling group will be placed as it had [Alignment.Start] align
82      * in [Column], and the alignment of the other siblings will be then determined such that
83      * the alignment lines coincide. Note that if only one element in a [Column] has the
84      * [alignBy] modifier specified the element will be positioned
85      * as if it had [Alignment.Start] align.
86      *
87      * Example usage:
88      * @sample androidx.compose.foundation.layout.samples.SimpleRelativeToSiblings
89      */
90     @Stable
91     public fun Modifier.alignBy(alignmentLineBlock: (Measured) -> Int): Modifier
92 }
93 
94 internal object FoldAwareColumnScopeInstance : FoldAwareColumnScope {
95     @Stable
96     override fun Modifier.ignoreFold() = this.then(
97         IgnoreFoldModifier(
98             inspectorInfo = debugInspectorInfo {
99                 name = "ignoreFold"
100                 value = true
101             }
102         )
103     )
104 
105     @Stable
106     override fun Modifier.align(alignment: Alignment.Horizontal) = this.then(
107         HorizontalAlignModifier(
108             horizontal = alignment,
109             inspectorInfo = debugInspectorInfo {
110                 name = "align"
111                 value = alignment
112             }
113         )
114     )
115 
116     @Stable
117     override fun Modifier.alignBy(alignmentLine: VerticalAlignmentLine) = this.then(
118         SiblingsAlignedModifier.WithAlignmentLine(
119             alignmentLine = alignmentLine,
120             inspectorInfo = debugInspectorInfo {
121                 name = "alignBy"
122                 value = alignmentLine
123             }
124         )
125     )
126 
127     @Stable
128     override fun Modifier.alignBy(alignmentLineBlock: (Measured) -> Int) = this.then(
129         SiblingsAlignedModifier.WithAlignmentLineBlock(
130             block = alignmentLineBlock,
131             inspectorInfo = debugInspectorInfo {
132                 name = "alignBy"
133                 value = alignmentLineBlock
134             }
135         )
136     )
137 }
138