1 /*
<lambda>null2  * 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.foundation.text
18 
19 import androidx.compose.runtime.getValue
20 import androidx.compose.runtime.remember
21 import androidx.compose.ui.Modifier
22 import androidx.compose.ui.composed
23 import androidx.compose.ui.layout.layout
24 import androidx.compose.ui.platform.LocalDensity
25 import androidx.compose.ui.platform.LocalFontFamilyResolver
26 import androidx.compose.ui.platform.LocalLayoutDirection
27 import androidx.compose.ui.text.TextStyle
28 import androidx.compose.ui.text.font.FontFamily
29 import androidx.compose.ui.text.font.FontStyle
30 import androidx.compose.ui.text.font.FontSynthesis
31 import androidx.compose.ui.text.font.FontWeight
32 import androidx.compose.ui.text.resolveDefaults
33 import androidx.compose.ui.unit.Density
34 import androidx.compose.ui.unit.IntSize
35 import androidx.compose.ui.unit.LayoutDirection
36 
37 internal fun Modifier.textFieldMinSize(style: TextStyle) = composed {
38     val density = LocalDensity.current
39     val fontFamilyResolver = LocalFontFamilyResolver.current
40     val layoutDirection = LocalLayoutDirection.current
41 
42     val resolvedStyle = remember(style, layoutDirection) { resolveDefaults(style, layoutDirection) }
43     val typeface by
44         remember(fontFamilyResolver, resolvedStyle) {
45             fontFamilyResolver.resolve(
46                 resolvedStyle.fontFamily,
47                 resolvedStyle.fontWeight ?: FontWeight.Normal,
48                 resolvedStyle.fontStyle ?: FontStyle.Normal,
49                 resolvedStyle.fontSynthesis ?: FontSynthesis.All
50             )
51         }
52 
53     val minSizeState = remember {
54         TextFieldSize(layoutDirection, density, fontFamilyResolver, style, typeface)
55     }
56 
57     minSizeState.update(layoutDirection, density, fontFamilyResolver, resolvedStyle, typeface)
58 
59     Modifier.layout { measurable, constraints ->
60         val minSize = minSizeState.minSize
61 
62         val childConstraints =
63             constraints.copy(
64                 minWidth = minSize.width.coerceIn(constraints.minWidth, constraints.maxWidth),
65                 minHeight = minSize.height.coerceIn(constraints.minHeight, constraints.maxHeight)
66             )
67         val measured = measurable.measure(childConstraints)
68         layout(measured.width, measured.height) { measured.placeRelative(0, 0) }
69     }
70 }
71 
72 private class TextFieldSize(
73     var layoutDirection: LayoutDirection,
74     var density: Density,
75     var fontFamilyResolver: FontFamily.Resolver,
76     var resolvedStyle: TextStyle,
77     var typeface: Any
78 ) {
79     var minSize = computeMinSize()
80         private set
81 
updatenull82     fun update(
83         layoutDirection: LayoutDirection,
84         density: Density,
85         fontFamilyResolver: FontFamily.Resolver,
86         resolvedStyle: TextStyle,
87         typeface: Any
88     ) {
89         if (
90             layoutDirection != this.layoutDirection ||
91                 density != this.density ||
92                 fontFamilyResolver != this.fontFamilyResolver ||
93                 resolvedStyle != this.resolvedStyle ||
94                 typeface != this.typeface
95         ) {
96             this.layoutDirection = layoutDirection
97             this.density = density
98             this.fontFamilyResolver = fontFamilyResolver
99             this.resolvedStyle = resolvedStyle
100             this.typeface = typeface
101             minSize = computeMinSize()
102         }
103     }
104 
computeMinSizenull105     private fun computeMinSize(): IntSize {
106         return computeSizeForDefaultText(
107             style = resolvedStyle,
108             density = density,
109             fontFamilyResolver = fontFamilyResolver
110         )
111     }
112 }
113