1 /*
2  * Copyright 2025 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.wear.protolayout.material3
18 
19 import androidx.annotation.Dimension
20 import androidx.annotation.Dimension.Companion.DP
21 import androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters
22 import androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec
23 import androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing
24 import androidx.wear.protolayout.types.LayoutColor
25 
26 /**
27  * Represents the indicator and track colors used in progress indicator.
28  *
29  * @param indicatorColor Color used to draw the indicator of progress indicator.
30  * @param trackColor Color used to draw the track of progress indicator.
31  * @param trackOverflowColor Color used to draw the track for progress overflow (>1).
32  */
33 public class ProgressIndicatorColors(
34     public val indicatorColor: LayoutColor,
35     public val trackColor: LayoutColor,
36     public val trackOverflowColor: LayoutColor = trackColor
37 ) {
38     /**
39      * Returns a copy of this [ProgressIndicatorColors], optionally overriding some of the values.
40      *
41      * @param indicatorColor Color used to draw the indicator of progress indicator.
42      * @param trackColor Color used to draw the track of progress indicator.
43      * @param trackOverflowColor Color used to draw the track for progress overflow (>1).
44      */
copynull45     public fun copy(
46         indicatorColor: LayoutColor = this.indicatorColor,
47         trackColor: LayoutColor = this.trackColor,
48         trackOverflowColor: LayoutColor = this.trackOverflowColor
49     ): ProgressIndicatorColors =
50         ProgressIndicatorColors(
51             indicatorColor = indicatorColor,
52             trackColor = trackColor,
53             trackOverflowColor = trackOverflowColor
54         )
55 }
56 
57 public object CircularProgressIndicatorDefaults {
58     /**
59      * Returns the recommended [ProgressIndicatorColors] object to be used when placing the progress
60      * indicator inside a graphic card with [CardDefaults.filledCardColors] from the given
61      * [MaterialScope]'s [ColorScheme].
62      */
63     public fun MaterialScope.filledProgressIndicatorColors(): ProgressIndicatorColors =
64         ProgressIndicatorColors(
65             theme.colorScheme.onPrimary,
66             theme.colorScheme.onPrimary.withOpacity(0.2F),
67             theme.colorScheme.onPrimary.withOpacity(0.6F)
68         )
69 
70     /**
71      * Returns the recommended [ProgressIndicatorColors] object to be used when placing the progress
72      * indicator inside a graphic card with [CardDefaults.filledTonalCardColors] from the given
73      * [MaterialScope]'s [ColorScheme].
74      */
75     public fun MaterialScope.filledTonalProgressIndicatorColors(): ProgressIndicatorColors =
76         ProgressIndicatorColors(
77             theme.colorScheme.primary,
78             theme.colorScheme.primary.withOpacity(0.2F),
79             theme.colorScheme.primary.withOpacity(0.6F)
80         )
81 
82     /**
83      * Returns the recommended [ProgressIndicatorColors] object to be used when placing the progress
84      * indicator inside a graphic card with [CardDefaults.filledVariantCardColors] from the given
85      * [MaterialScope]'s [ColorScheme].
86      */
87     public fun MaterialScope.filledVariantProgressIndicatorColors(): ProgressIndicatorColors =
88         ProgressIndicatorColors(
89             theme.colorScheme.onPrimaryContainer,
90             theme.colorScheme.onPrimaryContainer.withOpacity(0.2F),
91             theme.colorScheme.onPrimaryContainer.withOpacity(0.6F),
92         )
93 
94     /**
95      * The recommended animation spec for animations from current progress to a new progress value.
96      */
97     public val recommendedAnimationSpec: AnimationSpec =
98         AnimationSpec.Builder()
99             .setAnimationParameters(
100                 AnimationParameters.Builder()
101                     .setDurationMillis(450)
102                     .setEasing(Easing.cubicBezier(0.2f, 0f, 0f, 1f))
103                     .build()
104             )
105             .build()
106 
107     /** Large stroke width for circular progress indicator. */
108     @Dimension(DP) public const val LARGE_STROKE_WIDTH: Float = 8F
109 
110     /** Small stroke width for circular progress indicator. */
111     @Dimension(DP) public const val SMALL_STROKE_WIDTH: Float = 4F
112 
113     /**
114      * Returns recommended size of the gap based on [strokeWidth].
115      *
116      * The absolute value can be customized with `gapSize` parameter on [circularProgressIndicator].
117      */
118     @Dimension(DP)
119     public fun calculateRecommendedGapSize(@Dimension(DP) strokeWidth: Float): Float =
120         strokeWidth / 3F
121 
122     internal const val METADATA_TAG: String = "M3CPI"
123     /**
124      * A small offset to make the progress arc remaining when the progress is 1, with the module
125      * operation applied for handling overflow.
126      */
127     internal const val TRIVIAL_ARC_OFFSET: Float = 0.05f
128 
129     /**
130      * Extra stroke width for progress arc to prevent aliasing issue where the progress arc draws on
131      * top of the track arc where there are multiple segments.
132      */
133     internal const val INDICATOR_STROKE_WIDTH_INCREMENT_PX: Float = 1.5f
134 
135     /**
136      * Extra gap size in pixels between track arc segments to make the each track arc segment
137      * slightly shorter than the indicator arc segment on its top, so that it can be fully covered
138      * by the indicator on segment ends to prevent aliasing issue.
139      */
140     internal const val TRACK_GAP_SIZE_INCREMENT_PX: Float = 1f
141 
142     /** Default size for the fallback implementation. */
143     @Dimension(DP) internal const val CPI_DEFAULT_DP_SIZE: Float = 52F
144 }
145