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 
17 package androidx.glance.color
18 
19 import androidx.annotation.RestrictTo
20 import androidx.compose.ui.graphics.Color
21 import androidx.glance.R
22 import androidx.glance.unit.ColorProvider
23 
24 /**
25  * Holds a set of Glance specific [ColorProvider] that can be used to represent a Material 3 color
26  * scheme.
27  */
28 sealed class ColorProviders {
29 
30     val primary: ColorProvider
31     val onPrimary: ColorProvider
32     val primaryContainer: ColorProvider
33     val onPrimaryContainer: ColorProvider
34     val secondary: ColorProvider
35     val onSecondary: ColorProvider
36     val secondaryContainer: ColorProvider
37     val onSecondaryContainer: ColorProvider
38     val tertiary: ColorProvider
39     val onTertiary: ColorProvider
40     val tertiaryContainer: ColorProvider
41     val onTertiaryContainer: ColorProvider
42     val error: ColorProvider
43     val errorContainer: ColorProvider
44     val onError: ColorProvider
45     val onErrorContainer: ColorProvider
46     val background: ColorProvider
47     val onBackground: ColorProvider
48     val surface: ColorProvider
49     val onSurface: ColorProvider
50     val surfaceVariant: ColorProvider
51     val onSurfaceVariant: ColorProvider
52     val outline: ColorProvider
53     val inverseOnSurface: ColorProvider
54     val inverseSurface: ColorProvider
55     val inversePrimary: ColorProvider
56     val widgetBackground: ColorProvider
57 
58     constructor(
59         primary: ColorProvider,
60         onPrimary: ColorProvider,
61         primaryContainer: ColorProvider,
62         onPrimaryContainer: ColorProvider,
63         secondary: ColorProvider,
64         onSecondary: ColorProvider,
65         secondaryContainer: ColorProvider,
66         onSecondaryContainer: ColorProvider,
67         tertiary: ColorProvider,
68         onTertiary: ColorProvider,
69         tertiaryContainer: ColorProvider,
70         onTertiaryContainer: ColorProvider,
71         error: ColorProvider,
72         errorContainer: ColorProvider,
73         onError: ColorProvider,
74         onErrorContainer: ColorProvider,
75         background: ColorProvider,
76         onBackground: ColorProvider,
77         surface: ColorProvider,
78         onSurface: ColorProvider,
79         surfaceVariant: ColorProvider,
80         onSurfaceVariant: ColorProvider,
81         outline: ColorProvider,
82         inverseOnSurface: ColorProvider,
83         inverseSurface: ColorProvider,
84         inversePrimary: ColorProvider,
85         widgetBackground: ColorProvider,
86     ) {
87         this.primary = primary
88         this.onPrimary = onPrimary
89         this.primaryContainer = primaryContainer
90         this.onPrimaryContainer = onPrimaryContainer
91         this.secondary = secondary
92         this.onSecondary = onSecondary
93         this.secondaryContainer = secondaryContainer
94         this.onSecondaryContainer = onSecondaryContainer
95         this.tertiary = tertiary
96         this.onTertiary = onTertiary
97         this.tertiaryContainer = tertiaryContainer
98         this.onTertiaryContainer = onTertiaryContainer
99         this.error = error
100         this.errorContainer = errorContainer
101         this.onError = onError
102         this.onErrorContainer = onErrorContainer
103         this.background = background
104         this.onBackground = onBackground
105         this.surface = surface
106         this.onSurface = onSurface
107         this.surfaceVariant = surfaceVariant
108         this.onSurfaceVariant = onSurfaceVariant
109         this.outline = outline
110         this.inverseOnSurface = inverseOnSurface
111         this.inverseSurface = inverseSurface
112         this.inversePrimary = inversePrimary
113         this.widgetBackground = widgetBackground
114     }
115 
116     @Deprecated("Hidden")
117     constructor(
118         primary: ColorProvider,
119         onPrimary: ColorProvider,
120         primaryContainer: ColorProvider,
121         onPrimaryContainer: ColorProvider,
122         secondary: ColorProvider,
123         onSecondary: ColorProvider,
124         secondaryContainer: ColorProvider,
125         onSecondaryContainer: ColorProvider,
126         tertiary: ColorProvider,
127         onTertiary: ColorProvider,
128         tertiaryContainer: ColorProvider,
129         onTertiaryContainer: ColorProvider,
130         error: ColorProvider,
131         errorContainer: ColorProvider,
132         onError: ColorProvider,
133         onErrorContainer: ColorProvider,
134         background: ColorProvider,
135         onBackground: ColorProvider,
136         surface: ColorProvider,
137         onSurface: ColorProvider,
138         surfaceVariant: ColorProvider,
139         onSurfaceVariant: ColorProvider,
140         outline: ColorProvider,
141         inverseOnSurface: ColorProvider,
142         inverseSurface: ColorProvider,
143         inversePrimary: ColorProvider,
144     ) {
145         this.primary = primary
146         this.onPrimary = onPrimary
147         this.primaryContainer = primaryContainer
148         this.onPrimaryContainer = onPrimaryContainer
149         this.secondary = secondary
150         this.onSecondary = onSecondary
151         this.secondaryContainer = secondaryContainer
152         this.onSecondaryContainer = onSecondaryContainer
153         this.tertiary = tertiary
154         this.onTertiary = onTertiary
155         this.tertiaryContainer = tertiaryContainer
156         this.onTertiaryContainer = onTertiaryContainer
157         this.error = error
158         this.errorContainer = errorContainer
159         this.onError = onError
160         this.onErrorContainer = onErrorContainer
161         this.background = background
162         this.onBackground = onBackground
163         this.surface = surface
164         this.onSurface = onSurface
165         this.surfaceVariant = surfaceVariant
166         this.onSurfaceVariant = onSurfaceVariant
167         this.outline = outline
168         this.inverseOnSurface = inverseOnSurface
169         this.inverseSurface = inverseSurface
170         this.inversePrimary = inversePrimary
171         this.widgetBackground = ColorProvider(Color.Unspecified)
172     }
173 
equalsnull174     override fun equals(other: Any?): Boolean {
175         if (this === other) return true
176         if (javaClass != other?.javaClass) return false
177 
178         other as ColorProviders
179 
180         if (primary != other.primary) return false
181         if (onPrimary != other.onPrimary) return false
182         if (primaryContainer != other.primaryContainer) return false
183         if (onPrimaryContainer != other.onPrimaryContainer) return false
184         if (secondary != other.secondary) return false
185         if (onSecondary != other.onSecondary) return false
186         if (secondaryContainer != other.secondaryContainer) return false
187         if (onSecondaryContainer != other.onSecondaryContainer) return false
188         if (tertiary != other.tertiary) return false
189         if (onTertiary != other.onTertiary) return false
190         if (tertiaryContainer != other.tertiaryContainer) return false
191         if (onTertiaryContainer != other.onTertiaryContainer) return false
192         if (error != other.error) return false
193         if (errorContainer != other.errorContainer) return false
194         if (onError != other.onError) return false
195         if (onErrorContainer != other.onErrorContainer) return false
196         if (background != other.background) return false
197         if (onBackground != other.onBackground) return false
198         if (surface != other.surface) return false
199         if (onSurface != other.onSurface) return false
200         if (surfaceVariant != other.surfaceVariant) return false
201         if (onSurfaceVariant != other.onSurfaceVariant) return false
202         if (outline != other.outline) return false
203         if (inverseOnSurface != other.inverseOnSurface) return false
204         if (inverseSurface != other.inverseSurface) return false
205         if (inversePrimary != other.inversePrimary) return false
206         if (widgetBackground != other.widgetBackground) return false
207 
208         return true
209     }
210 
hashCodenull211     override fun hashCode(): Int {
212         var result = primary.hashCode()
213         result = 31 * result + onPrimary.hashCode()
214         result = 31 * result + primaryContainer.hashCode()
215         result = 31 * result + onPrimaryContainer.hashCode()
216         result = 31 * result + secondary.hashCode()
217         result = 31 * result + onSecondary.hashCode()
218         result = 31 * result + secondaryContainer.hashCode()
219         result = 31 * result + onSecondaryContainer.hashCode()
220         result = 31 * result + tertiary.hashCode()
221         result = 31 * result + onTertiary.hashCode()
222         result = 31 * result + tertiaryContainer.hashCode()
223         result = 31 * result + onTertiaryContainer.hashCode()
224         result = 31 * result + error.hashCode()
225         result = 31 * result + errorContainer.hashCode()
226         result = 31 * result + onError.hashCode()
227         result = 31 * result + onErrorContainer.hashCode()
228         result = 31 * result + background.hashCode()
229         result = 31 * result + onBackground.hashCode()
230         result = 31 * result + surface.hashCode()
231         result = 31 * result + onSurface.hashCode()
232         result = 31 * result + surfaceVariant.hashCode()
233         result = 31 * result + onSurfaceVariant.hashCode()
234         result = 31 * result + outline.hashCode()
235         result = 31 * result + inverseOnSurface.hashCode()
236         result = 31 * result + inverseSurface.hashCode()
237         result = 31 * result + inversePrimary.hashCode()
238         result = 31 * result + widgetBackground.hashCode()
239         return result
240     }
241 
toStringnull242     override fun toString(): String {
243         return "ColorProviders(primary=$primary," +
244             " onPrimary=$onPrimary, " +
245             "primaryContainer=$primaryContainer, " +
246             "onPrimaryContainer=$onPrimaryContainer, " +
247             "secondary=$secondary, " +
248             "onSecondary=$onSecondary, " +
249             "secondaryContainer=$secondaryContainer, " +
250             "onSecondaryContainer=$onSecondaryContainer, " +
251             "tertiary=$tertiary, " +
252             "onTertiary=$onTertiary, " +
253             "tertiaryContainer=$tertiaryContainer, " +
254             "onTertiaryContainer=$onTertiaryContainer, " +
255             "error=$error, " +
256             "errorContainer=$errorContainer, " +
257             "onError=$onError, " +
258             "onErrorContainer=$onErrorContainer, " +
259             "background=$background, " +
260             "onBackground=$onBackground, " +
261             "surface=$surface, " +
262             "onSurface=$onSurface, " +
263             "surfaceVariant=$surfaceVariant, " +
264             "onSurfaceVariant=$onSurfaceVariant, " +
265             "outline=$outline, " +
266             "inverseOnSurface=$inverseOnSurface, " +
267             "inverseSurface=$inverseSurface, " +
268             "inversePrimary=$inversePrimary)" +
269             "widgetBackground=$widgetBackground"
270     }
271 }
272 
273 /**
274  * Creates a set of color providers that represents a Material 3 style dynamic color theme. On
275  * devices that support it, this theme is derived from the user specific platform colors, on other
276  * devices this falls back to the Material baseline theme.
277  */
278 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
279 object DynamicThemeColorProviders :
280     ColorProviders(
281         primary = ColorProvider(R.color.glance_colorPrimary),
282         onPrimary = ColorProvider(R.color.glance_colorOnPrimary),
283         primaryContainer = ColorProvider(R.color.glance_colorPrimaryContainer),
284         onPrimaryContainer = ColorProvider(R.color.glance_colorOnPrimaryContainer),
285         secondary = ColorProvider(R.color.glance_colorSecondary),
286         onSecondary = ColorProvider(R.color.glance_colorOnSecondary),
287         secondaryContainer = ColorProvider(R.color.glance_colorSecondaryContainer),
288         onSecondaryContainer = ColorProvider(R.color.glance_colorOnSecondaryContainer),
289         tertiary = ColorProvider(R.color.glance_colorTertiary),
290         onTertiary = ColorProvider(R.color.glance_colorOnTertiary),
291         tertiaryContainer = ColorProvider(R.color.glance_colorTertiaryContainer),
292         onTertiaryContainer = ColorProvider(R.color.glance_colorOnTertiaryContainer),
293         error = ColorProvider(R.color.glance_colorError),
294         errorContainer = ColorProvider(R.color.glance_colorErrorContainer),
295         onError = ColorProvider(R.color.glance_colorOnError),
296         onErrorContainer = ColorProvider(R.color.glance_colorOnErrorContainer),
297         background = ColorProvider(R.color.glance_colorBackground),
298         onBackground = ColorProvider(R.color.glance_colorOnBackground),
299         surface = ColorProvider(R.color.glance_colorSurface),
300         onSurface = ColorProvider(R.color.glance_colorOnSurface),
301         surfaceVariant = ColorProvider(R.color.glance_colorSurfaceVariant),
302         onSurfaceVariant = ColorProvider(R.color.glance_colorOnSurfaceVariant),
303         outline = ColorProvider(R.color.glance_colorOutline),
304         inverseOnSurface = ColorProvider(R.color.glance_colorOnSurfaceInverse),
305         inverseSurface = ColorProvider(R.color.glance_colorSurfaceInverse),
306         inversePrimary = ColorProvider(R.color.glance_colorPrimaryInverse),
307         widgetBackground = ColorProvider(R.color.glance_colorWidgetBackground),
308     )
309 
310 internal class CustomColorProviders(
311     primary: ColorProvider,
312     onPrimary: ColorProvider,
313     primaryContainer: ColorProvider,
314     onPrimaryContainer: ColorProvider,
315     secondary: ColorProvider,
316     onSecondary: ColorProvider,
317     secondaryContainer: ColorProvider,
318     onSecondaryContainer: ColorProvider,
319     tertiary: ColorProvider,
320     onTertiary: ColorProvider,
321     tertiaryContainer: ColorProvider,
322     onTertiaryContainer: ColorProvider,
323     error: ColorProvider,
324     errorContainer: ColorProvider,
325     onError: ColorProvider,
326     onErrorContainer: ColorProvider,
327     background: ColorProvider,
328     onBackground: ColorProvider,
329     surface: ColorProvider,
330     onSurface: ColorProvider,
331     surfaceVariant: ColorProvider,
332     onSurfaceVariant: ColorProvider,
333     outline: ColorProvider,
334     inverseOnSurface: ColorProvider,
335     inverseSurface: ColorProvider,
336     inversePrimary: ColorProvider,
337     widgetBackground: ColorProvider,
338 ) :
339     ColorProviders(
340         primary = primary,
341         onPrimary = onPrimary,
342         primaryContainer = primaryContainer,
343         onPrimaryContainer = onPrimaryContainer,
344         secondary = secondary,
345         onSecondary = onSecondary,
346         secondaryContainer = secondaryContainer,
347         onSecondaryContainer = onSecondaryContainer,
348         tertiary = tertiary,
349         onTertiary = onTertiary,
350         tertiaryContainer = tertiaryContainer,
351         onTertiaryContainer = onTertiaryContainer,
352         error = error,
353         errorContainer = errorContainer,
354         onError = onError,
355         onErrorContainer = onErrorContainer,
356         background = background,
357         onBackground = onBackground,
358         surface = surface,
359         onSurface = onSurface,
360         surfaceVariant = surfaceVariant,
361         onSurfaceVariant = onSurfaceVariant,
362         outline = outline,
363         inverseOnSurface = inverseOnSurface,
364         inverseSurface = inverseSurface,
365         inversePrimary = inversePrimary,
366         widgetBackground = widgetBackground,
367     )
368 
colorProvidersnull369 fun colorProviders(
370     primary: ColorProvider,
371     onPrimary: ColorProvider,
372     primaryContainer: ColorProvider,
373     onPrimaryContainer: ColorProvider,
374     secondary: ColorProvider,
375     onSecondary: ColorProvider,
376     secondaryContainer: ColorProvider,
377     onSecondaryContainer: ColorProvider,
378     tertiary: ColorProvider,
379     onTertiary: ColorProvider,
380     tertiaryContainer: ColorProvider,
381     onTertiaryContainer: ColorProvider,
382     error: ColorProvider,
383     errorContainer: ColorProvider,
384     onError: ColorProvider,
385     onErrorContainer: ColorProvider,
386     background: ColorProvider,
387     onBackground: ColorProvider,
388     surface: ColorProvider,
389     onSurface: ColorProvider,
390     surfaceVariant: ColorProvider,
391     onSurfaceVariant: ColorProvider,
392     outline: ColorProvider,
393     inverseOnSurface: ColorProvider,
394     inverseSurface: ColorProvider,
395     inversePrimary: ColorProvider,
396     widgetBackground: ColorProvider,
397 ): ColorProviders =
398     CustomColorProviders(
399         primary = primary,
400         onPrimary = onPrimary,
401         primaryContainer = primaryContainer,
402         onPrimaryContainer = onPrimaryContainer,
403         secondary = secondary,
404         onSecondary = onSecondary,
405         secondaryContainer = secondaryContainer,
406         onSecondaryContainer = onSecondaryContainer,
407         tertiary = tertiary,
408         onTertiary = onTertiary,
409         tertiaryContainer = tertiaryContainer,
410         onTertiaryContainer = onTertiaryContainer,
411         error = error,
412         errorContainer = errorContainer,
413         onError = onError,
414         onErrorContainer = onErrorContainer,
415         background = background,
416         onBackground = onBackground,
417         surface = surface,
418         onSurface = onSurface,
419         surfaceVariant = surfaceVariant,
420         onSurfaceVariant = onSurfaceVariant,
421         outline = outline,
422         inverseOnSurface = inverseOnSurface,
423         inverseSurface = inverseSurface,
424         inversePrimary = inversePrimary,
425         widgetBackground = widgetBackground,
426     )
427 
428 fun colorProviders(
429     primary: ColorProvider,
430     onPrimary: ColorProvider,
431     primaryContainer: ColorProvider,
432     onPrimaryContainer: ColorProvider,
433     secondary: ColorProvider,
434     onSecondary: ColorProvider,
435     secondaryContainer: ColorProvider,
436     onSecondaryContainer: ColorProvider,
437     tertiary: ColorProvider,
438     onTertiary: ColorProvider,
439     tertiaryContainer: ColorProvider,
440     onTertiaryContainer: ColorProvider,
441     error: ColorProvider,
442     errorContainer: ColorProvider,
443     onError: ColorProvider,
444     onErrorContainer: ColorProvider,
445     background: ColorProvider,
446     onBackground: ColorProvider,
447     surface: ColorProvider,
448     onSurface: ColorProvider,
449     surfaceVariant: ColorProvider,
450     onSurfaceVariant: ColorProvider,
451     outline: ColorProvider,
452     inverseOnSurface: ColorProvider,
453     inverseSurface: ColorProvider,
454     inversePrimary: ColorProvider,
455 ): ColorProviders =
456     CustomColorProviders(
457         primary = primary,
458         onPrimary = onPrimary,
459         primaryContainer = primaryContainer,
460         onPrimaryContainer = onPrimaryContainer,
461         secondary = secondary,
462         onSecondary = onSecondary,
463         secondaryContainer = secondaryContainer,
464         onSecondaryContainer = onSecondaryContainer,
465         tertiary = tertiary,
466         onTertiary = onTertiary,
467         tertiaryContainer = tertiaryContainer,
468         onTertiaryContainer = onTertiaryContainer,
469         error = error,
470         errorContainer = errorContainer,
471         onError = onError,
472         onErrorContainer = onErrorContainer,
473         background = background,
474         onBackground = onBackground,
475         surface = surface,
476         onSurface = onSurface,
477         surfaceVariant = surfaceVariant,
478         onSurfaceVariant = onSurfaceVariant,
479         outline = outline,
480         inverseOnSurface = inverseOnSurface,
481         inverseSurface = inverseSurface,
482         inversePrimary = inversePrimary,
483         widgetBackground = ColorProvider(Color.Unspecified),
484     )
485