• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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  *      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 com.android.permissioncontroller.wear.permission.components.material2
18 
19 import android.graphics.drawable.Drawable
20 import androidx.annotation.StringRes
21 import androidx.compose.foundation.layout.BoxScope
22 import androidx.compose.foundation.layout.PaddingValues
23 import androidx.compose.foundation.layout.Row
24 import androidx.compose.foundation.layout.RowScope
25 import androidx.compose.foundation.layout.fillMaxWidth
26 import androidx.compose.foundation.layout.size
27 import androidx.compose.foundation.shape.CircleShape
28 import androidx.compose.foundation.shape.RoundedCornerShape
29 import androidx.compose.runtime.Composable
30 import androidx.compose.ui.Modifier
31 import androidx.compose.ui.draw.clip
32 import androidx.compose.ui.graphics.Color
33 import androidx.compose.ui.graphics.vector.ImageVector
34 import androidx.compose.ui.res.painterResource
35 import androidx.compose.ui.res.stringResource
36 import androidx.compose.ui.text.style.Hyphens
37 import androidx.compose.ui.text.style.TextAlign
38 import androidx.compose.ui.text.style.TextOverflow
39 import androidx.compose.ui.unit.dp
40 import androidx.wear.compose.material.Chip
41 import androidx.wear.compose.material.ChipColors
42 import androidx.wear.compose.material.ChipDefaults
43 import androidx.wear.compose.material.ContentAlpha
44 import androidx.wear.compose.material.Icon
45 import androidx.wear.compose.material.MaterialTheme
46 import androidx.wear.compose.material.Text
47 import androidx.wear.compose.material.contentColorFor
48 import com.android.permissioncontroller.wear.permission.components.rememberDrawablePainter
49 
50 /**
51  * This component is an alternative to [Chip], providing the following:
52  * - a convenient way of providing a label and a secondary label;
53  * - a convenient way of providing an icon, and choosing their size based on the sizes recommended
54  *   by the Wear guidelines;
55  */
56 @Composable
Chipnull57 fun Chip(
58     label: String,
59     labelMaxLines: Int? = null,
60     onClick: () -> Unit,
61     modifier: Modifier = Modifier,
62     secondaryLabel: String? = null,
63     secondaryLabelMaxLines: Int? = null,
64     icon: Any? = null,
65     iconContentDescription: String? = null,
66     largeIcon: Boolean = false,
67     textColor: Color = MaterialTheme.colors.onSurface,
68     iconColor: Color = Color.Unspecified,
69     colors: ChipColors = chipDefaultColors(),
70     enabled: Boolean = true,
71 ) {
72     val iconParam: (@Composable BoxScope.() -> Unit)? =
73         icon?.let {
74             {
75                 val iconSize =
76                     if (largeIcon) {
77                         ChipDefaults.LargeIconSize
78                     } else {
79                         ChipDefaults.IconSize
80                     }
81 
82                 Row {
83                     val iconModifier = Modifier.size(iconSize).clip(CircleShape)
84                     when (icon) {
85                         is ImageVector ->
86                             Icon(
87                                 imageVector = icon,
88                                 tint = iconColor,
89                                 contentDescription = iconContentDescription,
90                                 modifier = iconModifier,
91                             )
92                         is Int ->
93                             Icon(
94                                 painter = painterResource(id = icon),
95                                 tint = iconColor,
96                                 contentDescription = iconContentDescription,
97                                 modifier = iconModifier,
98                             )
99                         is Drawable ->
100                             Icon(
101                                 painter = rememberDrawablePainter(icon),
102                                 tint = iconColor,
103                                 contentDescription = iconContentDescription,
104                                 modifier = iconModifier,
105                             )
106                         else -> {}
107                     }
108                 }
109             }
110         }
111 
112     Chip(
113         label = label,
114         labelMaxLines = labelMaxLines,
115         onClick = onClick,
116         modifier = modifier,
117         secondaryLabel = secondaryLabel,
118         secondaryLabelMaxLines = secondaryLabelMaxLines,
119         icon = iconParam,
120         largeIcon = largeIcon,
121         textColor = textColor,
122         colors = colors,
123         enabled = enabled,
124     )
125 }
126 
127 /**
128  * This component is an alternative to [Chip], providing the following:
129  * - a convenient way of providing a label and a secondary label;
130  * - a convenient way of providing an icon, and choosing their size based on the sizes recommended
131  *   by the Wear guidelines;
132  */
133 @Composable
Chipnull134 fun Chip(
135     @StringRes labelId: Int,
136     labelMaxLines: Int? = null,
137     onClick: () -> Unit,
138     modifier: Modifier = Modifier,
139     @StringRes secondaryLabel: Int? = null,
140     secondaryLabelMaxLines: Int? = null,
141     icon: Any? = null,
142     largeIcon: Boolean = false,
143     textColor: Color = MaterialTheme.colors.onSurface,
144     iconColor: Color = Color.Unspecified,
145     colors: ChipColors = chipDefaultColors(),
146     enabled: Boolean = true,
147 ) {
148     Chip(
149         label = stringResource(id = labelId),
150         labelMaxLines = labelMaxLines,
151         onClick = onClick,
152         modifier = modifier,
153         secondaryLabel = secondaryLabel?.let { stringResource(id = it) },
154         secondaryLabelMaxLines = secondaryLabelMaxLines,
155         icon = icon,
156         largeIcon = largeIcon,
157         textColor = textColor,
158         iconColor = iconColor,
159         colors = colors,
160         enabled = enabled,
161     )
162 }
163 
164 /**
165  * This component is an alternative to [Chip], providing the following:
166  * - a convenient way of providing a label and a secondary label;
167  */
168 // Setting the color as per
169 // https://source.corp.google.com/piper///depot/google3/java/com/google/android/clockwork/common/wearable/wearmaterial/button/res/color/wear_button_secondary_text_stateful.xml?q=wear_button_secondary_text_stateful
170 @Composable
Chipnull171 fun Chip(
172     label: String,
173     labelMaxLines: Int? = null,
174     onClick: () -> Unit,
175     modifier: Modifier = Modifier,
176     secondaryLabel: String? = null,
177     secondaryLabelMaxLines: Int? = null,
178     icon: (@Composable BoxScope.() -> Unit)? = null,
179     largeIcon: Boolean = false,
180     textColor: Color = MaterialTheme.colors.onSurface,
181     secondaryTextColor: Color = MaterialTheme.colors.primary,
182     colors: ChipColors = chipDefaultColors(),
183     enabled: Boolean = true,
184 ) {
185     val hasSecondaryLabel = secondaryLabel != null
186     val hasIcon = icon != null
187 
188     val labelParam: (@Composable RowScope.() -> Unit) = {
189         Text(
190             text = label,
191             color = textColor,
192             modifier = Modifier.fillMaxWidth(),
193             textAlign = if (hasSecondaryLabel || hasIcon) TextAlign.Start else TextAlign.Center,
194             overflow = TextOverflow.Ellipsis,
195             maxLines = labelMaxLines ?: if (hasSecondaryLabel) 1 else 2,
196             style = MaterialTheme.typography.button.copy(hyphens = Hyphens.Auto),
197         )
198     }
199 
200     val secondaryLabelParam: (@Composable RowScope.() -> Unit)? =
201         secondaryLabel?.let {
202             {
203                 Text(
204                     text = secondaryLabel,
205                     color = secondaryTextColor,
206                     overflow = TextOverflow.Ellipsis,
207                     maxLines = secondaryLabelMaxLines ?: 1,
208                     style = MaterialTheme.typography.caption2.copy(hyphens = Hyphens.Auto),
209                 )
210             }
211         }
212 
213     val contentPadding =
214         if (largeIcon) {
215             val verticalPadding = ChipDefaults.ChipVerticalPadding
216             PaddingValues(
217                 start = 10.dp,
218                 top = verticalPadding,
219                 end = ChipDefaults.ChipHorizontalPadding,
220                 bottom = verticalPadding,
221             )
222         } else {
223             ChipDefaults.ContentPadding
224         }
225 
226     Chip(
227         label = labelParam,
228         onClick = onClick,
229         modifier = modifier.fillMaxWidth(),
230         secondaryLabel = secondaryLabelParam,
231         icon = icon,
232         colors = colors,
233         enabled = enabled,
234         contentPadding = contentPadding,
235         shape = RoundedCornerShape(26.dp),
236     )
237 }
238 
239 /** Default colors of a Chip. */
chipDefaultColorsnull240 @Composable fun chipDefaultColors(): ChipColors = ChipDefaults.secondaryChipColors()
241 
242 /**
243  * ChipColors that disabled alpha is applied based on [ChipDefaults.secondaryChipColors()]. It is
244  * used for a Chip which would like to respond to click events, meanwhile it seems disabled.
245  */
246 @Composable
247 fun chipDisabledColors(): ChipColors {
248     val backgroundColor = MaterialTheme.colors.surface
249     val contentColor = contentColorFor(backgroundColor)
250     val secondaryContentColor = contentColor
251     val iconColor = contentColor
252 
253     return ChipDefaults.chipColors(
254         backgroundColor = backgroundColor.copy(alpha = ContentAlpha.disabled),
255         contentColor = contentColor.copy(alpha = ContentAlpha.disabled),
256         secondaryContentColor = secondaryContentColor.copy(alpha = ContentAlpha.disabled),
257         iconColor = iconColor.copy(alpha = ContentAlpha.disabled),
258     )
259 }
260