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 package com.android.customization.picker.color.ui.view
17 
18 import android.annotation.ColorInt
19 import android.content.Context
20 import android.graphics.Canvas
21 import android.graphics.Color
22 import android.graphics.Paint
23 import android.graphics.RectF
24 import android.util.AttributeSet
25 import android.view.View
26 
27 /**
28  * Draw a color option icon, which is a quadrant circle that can show at most 4 different colors.
29  */
30 class ColorOptionIconView(
31     context: Context,
32     attrs: AttributeSet,
33 ) : View(context, attrs) {
34 
<lambda>null35     private val paint = Paint().apply { style = Paint.Style.FILL }
36 
37     private val oval = RectF()
38 
39     private var color0 = DEFAULT_PLACEHOLDER_COLOR
40     private var color1 = DEFAULT_PLACEHOLDER_COLOR
41     private var color2 = DEFAULT_PLACEHOLDER_COLOR
42     private var color3 = DEFAULT_PLACEHOLDER_COLOR
43 
44     private var w = 0
45     private var h = 0
46 
47     /**
48      * @param color0 the color in the top left quadrant
49      * @param color1 the color in the top right quadrant
50      * @param color2 the color in the bottom left quadrant
51      * @param color3 the color in the bottom right quadrant
52      */
bindColornull53     fun bindColor(
54         @ColorInt color0: Int,
55         @ColorInt color1: Int,
56         @ColorInt color2: Int,
57         @ColorInt color3: Int,
58     ) {
59         this.color0 = color0
60         this.color1 = color1
61         this.color2 = color2
62         this.color3 = color3
63         invalidate()
64     }
65 
onSizeChangednull66     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
67         this.w = w
68         this.h = h
69         super.onSizeChanged(w, h, oldw, oldh)
70     }
71 
onDrawnull72     override fun onDraw(canvas: Canvas) {
73         super.onDraw(canvas)
74         // The w and h need to be an even number to avoid tiny pixel-level gaps between the pies
75         w = w.roundDownToEven()
76         h = h.roundDownToEven()
77 
78         val width = w.toFloat()
79         val height = h.toFloat()
80 
81         oval.set(0f, 0f, width, height)
82         canvas.apply {
83             paint.color = color3
84             drawArc(
85                 oval,
86                 0f,
87                 90f,
88                 true,
89                 paint,
90             )
91             paint.color = color2
92             drawArc(
93                 oval,
94                 90f,
95                 90f,
96                 true,
97                 paint,
98             )
99             paint.color = color0
100             drawArc(
101                 oval,
102                 180f,
103                 90f,
104                 true,
105                 paint,
106             )
107             paint.color = color1
108             drawArc(
109                 oval,
110                 270f,
111                 90f,
112                 true,
113                 paint,
114             )
115         }
116     }
117 
118     companion object {
119         const val DEFAULT_PLACEHOLDER_COLOR = Color.BLACK
120 
roundDownToEvennull121         fun Int.roundDownToEven(): Int {
122             return if (this % 2 == 0) this else this - 1
123         }
124     }
125 }
126