1 /*
2  * Copyright 2020 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.text
18 
19 import androidx.compose.runtime.Immutable
20 import androidx.compose.ui.text.internal.requirePrecondition
21 import androidx.compose.ui.unit.TextUnit
22 import androidx.compose.ui.unit.isUnspecified
23 
24 /**
25  * A placeholder is a rectangle box inserted into text, which tells the text processor to leave an
26  * empty space. It is typically used to insert inline image, custom emoji, etc into the text
27  * paragraph.
28  *
29  * @param width the width of the placeholder, it must be specified in sp or em.
30  *   [TextUnit.Unspecified] is not allowed.
31  * @param height the height of the placeholder, it must be specified in sp or em.
32  *   [TextUnit.Unspecified] is not allowed.
33  * @param placeholderVerticalAlign the vertical alignment of the placeholder within the text line.
34  *   Check [PlaceholderVerticalAlign] for more information.
35  * @throws IllegalArgumentException if [TextUnit.Unspecified] is passed to [width] or [height].
36  */
37 @Immutable
38 class Placeholder(
39     val width: TextUnit,
40     val height: TextUnit,
41     val placeholderVerticalAlign: PlaceholderVerticalAlign
42 ) {
43     init {
<lambda>null44         requirePrecondition(!width.isUnspecified) { "width cannot be TextUnit.Unspecified" }
<lambda>null45         requirePrecondition(!height.isUnspecified) { "height cannot be TextUnit.Unspecified" }
46     }
47 
copynull48     fun copy(
49         width: TextUnit = this.width,
50         height: TextUnit = this.height,
51         placeholderVerticalAlign: PlaceholderVerticalAlign = this.placeholderVerticalAlign
52     ): Placeholder {
53         return Placeholder(
54             width = width,
55             height = height,
56             placeholderVerticalAlign = placeholderVerticalAlign
57         )
58     }
59 
equalsnull60     override fun equals(other: Any?): Boolean {
61         if (this === other) return true
62         if (other !is Placeholder) return false
63         if (width != other.width) return false
64         if (height != other.height) return false
65         if (placeholderVerticalAlign != other.placeholderVerticalAlign) return false
66         return true
67     }
68 
hashCodenull69     override fun hashCode(): Int {
70         var result = width.hashCode()
71         result = 31 * result + height.hashCode()
72         result = 31 * result + placeholderVerticalAlign.hashCode()
73         return result
74     }
75 
toStringnull76     override fun toString(): String {
77         return "Placeholder(" +
78             "width=$width, " +
79             "height=$height, " +
80             "placeholderVerticalAlign=$placeholderVerticalAlign" +
81             ")"
82     }
83 }
84 
85 /**
86  * The settings used to specify how a placeholder is vertically aligned within a text line.
87  *
88  * @see Placeholder
89  */
90 @kotlin.jvm.JvmInline
91 value class PlaceholderVerticalAlign
92 internal constructor(@Suppress("unused") private val value: Int) {
93 
toStringnull94     override fun toString(): String {
95         return when (this) {
96             AboveBaseline -> "AboveBaseline"
97             Top -> "Top"
98             Bottom -> "Bottom"
99             Center -> "Center"
100             TextTop -> "TextTop"
101             TextBottom -> "TextBottom"
102             TextCenter -> "TextCenter"
103             else -> "Invalid"
104         }
105     }
106 
107     companion object {
108         /** Align the bottom of the placeholder with the baseline. */
109         val AboveBaseline = PlaceholderVerticalAlign(1)
110         /** Align the top of the placeholder with the top of the entire line. */
111         val Top = PlaceholderVerticalAlign(2)
112         /** Align the bottom of the placeholder with the bottom of the entire line. */
113         val Bottom = PlaceholderVerticalAlign(3)
114         /** Align the center of the placeholder with the center of the entire line. */
115         val Center = PlaceholderVerticalAlign(4)
116         /**
117          * Align the top of the placeholder with the top of the proceeding text. It is different
118          * from the [Top] when there are texts with different font size, font or other styles in the
119          * same line. This option will use the proceeding text's top instead of the whole line's
120          * top.
121          */
122         val TextTop = PlaceholderVerticalAlign(5)
123         /**
124          * Align the bottom of the placeholder with the bottom of the proceeding text. It is
125          * different from the [TextBottom] when there are texts with different font size, font or
126          * other styles in the same line. This option will use the proceeding text's bottom instead
127          * of the whole line's bottom.
128          */
129         val TextBottom = PlaceholderVerticalAlign(6)
130         /**
131          * Align the center of the placeholder with the center of the proceeding text. It is
132          * different from the [Center] when there are texts with different font size, font or other
133          * styles in the same line. This option will use the proceeding text's center instead of the
134          * whole line's center.
135          */
136         val TextCenter = PlaceholderVerticalAlign(7)
137     }
138 }
139