1 /*
2  * Copyright 2022 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 package androidx.compose.ui.layout
17 
18 import androidx.compose.ui.geometry.Offset
19 
20 /**
21  * A line that can be used to align layout children inside a [Placeable.PlacementScope].
22  *
23  * @see Placeable.PlacementScope.current
24  * @see MeasureScope.layout
25  * @see RulerScope.provides
26  * @see RulerScope.providesRelative
27  */
28 sealed class Ruler {
29     /**
30      * Returns the coordinate for the [Ruler], defined with the [coordinate] value at
31      * [sourceCoordinates] and read at [targetCoordinates].
32      */
calculateCoordinatenull33     internal abstract fun calculateCoordinate(
34         coordinate: Float,
35         sourceCoordinates: LayoutCoordinates,
36         targetCoordinates: LayoutCoordinates
37     ): Float
38 }
39 
40 /**
41  * A vertical [Ruler]. Defines a line that can be used by parent layouts to align or position their
42  * children horizontally. The position of the ruler can be retrieved with
43  * [Placeable.PlacementScope.current] and can be set with [MeasureScope.layout] using
44  * [RulerScope.provides] or [RulerScope.providesRelative].
45  */
46 class VerticalRuler() : Ruler() {
47     override fun calculateCoordinate(
48         coordinate: Float,
49         sourceCoordinates: LayoutCoordinates,
50         targetCoordinates: LayoutCoordinates
51     ): Float {
52         val offset = Offset(coordinate, sourceCoordinates.size.height / 2f)
53         return targetCoordinates.localPositionOf(sourceCoordinates, offset).x
54     }
55 }
56 
57 /**
58  * A horizontal [Ruler]. Defines a line that can be used by parent layouts to align or position
59  * their children vertically. The position of the ruler can be retrieved with
60  * [Placeable.PlacementScope.current] and can be set with [MeasureScope.layout] using
61  * [RulerScope.provides].
62  */
63 class HorizontalRuler : Ruler() {
calculateCoordinatenull64     override fun calculateCoordinate(
65         coordinate: Float,
66         sourceCoordinates: LayoutCoordinates,
67         targetCoordinates: LayoutCoordinates
68     ): Float {
69         val offset = Offset(sourceCoordinates.size.width / 2f, coordinate)
70         return targetCoordinates.localPositionOf(sourceCoordinates, offset).y
71     }
72 }
73