ColorProviders.kt

/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.glance.color

import androidx.annotation.RestrictTo
import androidx.glance.R
import androidx.glance.unit.ColorProvider

/**
 * Holds a set of Glance specific [ColorProvider] that can be used to represent a Material 3 color
 * scheme.
 */
sealed class ColorProviders(
    val primary: ColorProvider,
    val onPrimary: ColorProvider,
    val primaryContainer: ColorProvider,
    val onPrimaryContainer: ColorProvider,
    val secondary: ColorProvider,
    val onSecondary: ColorProvider,
    val secondaryContainer: ColorProvider,
    val onSecondaryContainer: ColorProvider,
    val tertiary: ColorProvider,
    val onTertiary: ColorProvider,
    val tertiaryContainer: ColorProvider,
    val onTertiaryContainer: ColorProvider,
    val error: ColorProvider,
    val errorContainer: ColorProvider,
    val onError: ColorProvider,
    val onErrorContainer: ColorProvider,
    val background: ColorProvider,
    val onBackground: ColorProvider,
    val surface: ColorProvider,
    val onSurface: ColorProvider,
    val surfaceVariant: ColorProvider,
    val onSurfaceVariant: ColorProvider,
    val outline: ColorProvider,
    val inverseOnSurface: ColorProvider,
    val inverseSurface: ColorProvider,
    val inversePrimary: ColorProvider
) {

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as ColorProviders

        if (primary != other.primary) return false
        if (onPrimary != other.onPrimary) return false
        if (primaryContainer != other.primaryContainer) return false
        if (onPrimaryContainer != other.onPrimaryContainer) return false
        if (secondary != other.secondary) return false
        if (onSecondary != other.onSecondary) return false
        if (secondaryContainer != other.secondaryContainer) return false
        if (onSecondaryContainer != other.onSecondaryContainer) return false
        if (tertiary != other.tertiary) return false
        if (onTertiary != other.onTertiary) return false
        if (tertiaryContainer != other.tertiaryContainer) return false
        if (onTertiaryContainer != other.onTertiaryContainer) return false
        if (error != other.error) return false
        if (errorContainer != other.errorContainer) return false
        if (onError != other.onError) return false
        if (onErrorContainer != other.onErrorContainer) return false
        if (background != other.background) return false
        if (onBackground != other.onBackground) return false
        if (surface != other.surface) return false
        if (onSurface != other.onSurface) return false
        if (surfaceVariant != other.surfaceVariant) return false
        if (onSurfaceVariant != other.onSurfaceVariant) return false
        if (outline != other.outline) return false
        if (inverseOnSurface != other.inverseOnSurface) return false
        if (inverseSurface != other.inverseSurface) return false
        if (inversePrimary != other.inversePrimary) return false

        return true
    }

    override fun hashCode(): Int {
        var result = primary.hashCode()
        result = 31 * result + onPrimary.hashCode()
        result = 31 * result + primaryContainer.hashCode()
        result = 31 * result + onPrimaryContainer.hashCode()
        result = 31 * result + secondary.hashCode()
        result = 31 * result + onSecondary.hashCode()
        result = 31 * result + secondaryContainer.hashCode()
        result = 31 * result + onSecondaryContainer.hashCode()
        result = 31 * result + tertiary.hashCode()
        result = 31 * result + onTertiary.hashCode()
        result = 31 * result + tertiaryContainer.hashCode()
        result = 31 * result + onTertiaryContainer.hashCode()
        result = 31 * result + error.hashCode()
        result = 31 * result + errorContainer.hashCode()
        result = 31 * result + onError.hashCode()
        result = 31 * result + onErrorContainer.hashCode()
        result = 31 * result + background.hashCode()
        result = 31 * result + onBackground.hashCode()
        result = 31 * result + surface.hashCode()
        result = 31 * result + onSurface.hashCode()
        result = 31 * result + surfaceVariant.hashCode()
        result = 31 * result + onSurfaceVariant.hashCode()
        result = 31 * result + outline.hashCode()
        result = 31 * result + inverseOnSurface.hashCode()
        result = 31 * result + inverseSurface.hashCode()
        result = 31 * result + inversePrimary.hashCode()
        return result
    }

    override fun toString(): String {
        return "ColorProviders(primary=$primary," +
            " onPrimary=$onPrimary, " +
            "primaryContainer=$primaryContainer, " +
            "onPrimaryContainer=$onPrimaryContainer, " +
            "secondary=$secondary, " +
            "onSecondary=$onSecondary, " +
            "secondaryContainer=$secondaryContainer, " +
            "onSecondaryContainer=$onSecondaryContainer, " +
            "tertiary=$tertiary, " +
            "onTertiary=$onTertiary, " +
            "tertiaryContainer=$tertiaryContainer, " +
            "onTertiaryContainer=$onTertiaryContainer, " +
            "error=$error, " +
            "errorContainer=$errorContainer, " +
            "onError=$onError, " +
            "onErrorContainer=$onErrorContainer, " +
            "background=$background, " +
            "onBackground=$onBackground, " +
            "surface=$surface, " +
            "onSurface=$onSurface, " +
            "surfaceVariant=$surfaceVariant, " +
            "onSurfaceVariant=$onSurfaceVariant, " +
            "outline=$outline, " +
            "inverseOnSurface=$inverseOnSurface, " +
            "inverseSurface=$inverseSurface, " +
            "inversePrimary=$inversePrimary)"
    }
}

/**
 * Creates a set of color providers that represents a Material 3 style dynamic color theme. On
 * devices that support it, this theme is derived from the user specific platform colors, on other
 * devices this falls back to the Material baseline theme.
 */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
object DynamicThemeColorProviders : ColorProviders(
    primary = ColorProvider(R.color.glance_colorPrimary),
    onPrimary = ColorProvider(R.color.glance_colorOnPrimary),
    primaryContainer = ColorProvider(R.color.glance_colorPrimaryContainer),
    onPrimaryContainer = ColorProvider(R.color.glance_colorOnPrimaryContainer),
    secondary = ColorProvider(R.color.glance_colorSecondary),
    onSecondary = ColorProvider(R.color.glance_colorOnSecondary),
    secondaryContainer = ColorProvider(R.color.glance_colorSecondaryContainer),
    onSecondaryContainer = ColorProvider(R.color.glance_colorOnSecondaryContainer),
    tertiary = ColorProvider(R.color.glance_colorTertiary),
    onTertiary = ColorProvider(R.color.glance_colorOnTertiary),
    tertiaryContainer = ColorProvider(R.color.glance_colorTertiaryContainer),
    onTertiaryContainer = ColorProvider(R.color.glance_colorOnTertiaryContainer),
    error = ColorProvider(R.color.glance_colorError),
    errorContainer = ColorProvider(R.color.glance_colorErrorContainer),
    onError = ColorProvider(R.color.glance_colorOnError),
    onErrorContainer = ColorProvider(R.color.glance_colorOnErrorContainer),
    background = ColorProvider(R.color.glance_colorBackground),
    onBackground = ColorProvider(R.color.glance_colorOnBackground),
    surface = ColorProvider(R.color.glance_colorSurface),
    onSurface = ColorProvider(R.color.glance_colorOnSurface),
    surfaceVariant = ColorProvider(R.color.glance_colorSurfaceVariant),
    onSurfaceVariant = ColorProvider(R.color.glance_colorOnSurfaceVariant),
    outline = ColorProvider(R.color.glance_colorOutline),
    inverseOnSurface = ColorProvider(R.color.glance_colorOnSurfaceInverse),
    inverseSurface = ColorProvider(R.color.glance_colorSurfaceInverse),
    inversePrimary = ColorProvider(R.color.glance_colorPrimaryInverse),
)

internal class CustomColorProviders(
    primary: ColorProvider,
    onPrimary: ColorProvider,
    primaryContainer: ColorProvider,
    onPrimaryContainer: ColorProvider,
    secondary: ColorProvider,
    onSecondary: ColorProvider,
    secondaryContainer: ColorProvider,
    onSecondaryContainer: ColorProvider,
    tertiary: ColorProvider,
    onTertiary: ColorProvider,
    tertiaryContainer: ColorProvider,
    onTertiaryContainer: ColorProvider,
    error: ColorProvider,
    errorContainer: ColorProvider,
    onError: ColorProvider,
    onErrorContainer: ColorProvider,
    background: ColorProvider,
    onBackground: ColorProvider,
    surface: ColorProvider,
    onSurface: ColorProvider,
    surfaceVariant: ColorProvider,
    onSurfaceVariant: ColorProvider,
    outline: ColorProvider,
    inverseOnSurface: ColorProvider,
    inverseSurface: ColorProvider,
    inversePrimary: ColorProvider
) : ColorProviders(
    primary = primary,
    onPrimary = onPrimary,
    primaryContainer = primaryContainer,
    onPrimaryContainer = onPrimaryContainer,
    secondary = secondary,
    onSecondary = onSecondary,
    secondaryContainer = secondaryContainer,
    onSecondaryContainer = onSecondaryContainer,
    tertiary = tertiary,
    onTertiary = onTertiary,
    tertiaryContainer = tertiaryContainer,
    onTertiaryContainer = onTertiaryContainer,
    error = error,
    errorContainer = errorContainer,
    onError = onError,
    onErrorContainer = onErrorContainer,
    background = background,
    onBackground = onBackground,
    surface = surface,
    onSurface = onSurface,
    surfaceVariant = surfaceVariant,
    onSurfaceVariant = onSurfaceVariant,
    outline = outline,
    inverseOnSurface = inverseOnSurface,
    inverseSurface = inverseSurface,
    inversePrimary = inversePrimary
)

fun colorProviders(
    primary: ColorProvider,
    onPrimary: ColorProvider,
    primaryContainer: ColorProvider,
    onPrimaryContainer: ColorProvider,
    secondary: ColorProvider,
    onSecondary: ColorProvider,
    secondaryContainer: ColorProvider,
    onSecondaryContainer: ColorProvider,
    tertiary: ColorProvider,
    onTertiary: ColorProvider,
    tertiaryContainer: ColorProvider,
    onTertiaryContainer: ColorProvider,
    error: ColorProvider,
    errorContainer: ColorProvider,
    onError: ColorProvider,
    onErrorContainer: ColorProvider,
    background: ColorProvider,
    onBackground: ColorProvider,
    surface: ColorProvider,
    onSurface: ColorProvider,
    surfaceVariant: ColorProvider,
    onSurfaceVariant: ColorProvider,
    outline: ColorProvider,
    inverseOnSurface: ColorProvider,
    inverseSurface: ColorProvider,
    inversePrimary: ColorProvider
): ColorProviders = CustomColorProviders(
    primary = primary,
    onPrimary = onPrimary,
    primaryContainer = primaryContainer,
    onPrimaryContainer = onPrimaryContainer,
    secondary = secondary,
    onSecondary = onSecondary,
    secondaryContainer = secondaryContainer,
    onSecondaryContainer = onSecondaryContainer,
    tertiary = tertiary,
    onTertiary = onTertiary,
    tertiaryContainer = tertiaryContainer,
    onTertiaryContainer = onTertiaryContainer,
    error = error,
    errorContainer = errorContainer,
    onError = onError,
    onErrorContainer = onErrorContainer,
    background = background,
    onBackground = onBackground,
    surface = surface,
    onSurface = onSurface,
    surfaceVariant = surfaceVariant,
    onSurfaceVariant = onSurfaceVariant,
    outline = outline,
    inverseOnSurface = inverseOnSurface,
    inverseSurface = inverseSurface,
    inversePrimary = inversePrimary
)