1a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford/*
2a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford * Copyright (C) 2013 The Android Open Source Project
3a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford *
4a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford * Licensed under the Apache License, Version 2.0 (the "License");
5a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford * you may not use this file except in compliance with the License.
6a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford * You may obtain a copy of the License at
7a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford *
8a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford *      http://www.apache.org/licenses/LICENSE-2.0
9a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford *
10a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford * Unless required by applicable law or agreed to in writing, software
11a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford * distributed under the License is distributed on an "AS IS" BASIS,
12a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford * See the License for the specific language governing permissions and
14a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford * limitations under the License.
15a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford */
16a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
17a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordpackage com.android.gallery3d.filtershow.colorpicker;
18a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
19a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.content.Context;
20a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.Bitmap;
21a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.Canvas;
22a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.Color;
23a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.LinearGradient;
24a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.Paint;
25a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.RadialGradient;
26a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.Rect;
27a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.RectF;
28a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.Shader;
29a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.graphics.SweepGradient;
30a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.util.AttributeSet;
31a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.util.DisplayMetrics;
32a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.view.MotionEvent;
33a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport android.view.View;
34a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
35a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport com.android.gallery3d.R;
36a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
37a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordimport java.util.ArrayList;
38a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
39a4f38c0f8f70c998391780b672eea5d5e49277c7John Hofordpublic class ColorSVRectView extends View implements ColorListener {
40a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private float mDpToPix;
41a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
42a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private float mCtrY = 100;
43a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private Paint mPaint1;
44a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
45a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private float mCtrX = 100;
46a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private Paint mDotPaint = new Paint();
47a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private float mDotRadus;
48a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private float mBorder;
49a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
50a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private float mDotX = Float.NaN;
51a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private float mDotY;
52a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private int mSliderColor = 0xFF33B5E5;
53a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private float[] mHSVO = new float[]{0, 1, 1, 1};
54a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    RectF mRect = new RectF();
55a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
56a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private int mWidth;
57a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private int mHeight;
58a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    public final static float DOT_SIZE = 20;
59a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    public final static float BORDER_SIZE = 20;
60a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    Bitmap mBitmap;
61a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
62a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    public ColorSVRectView(Context ctx, AttributeSet attrs) {
63a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        super(ctx, attrs);
64a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
65a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
66a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mDpToPix = metrics.density;
67a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mDotRadus = DOT_SIZE * mDpToPix;
68a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mBorder = BORDER_SIZE * mDpToPix;
69a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
70a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mPaint1 = new Paint();
71a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
72a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
73a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mDotPaint.setStyle(Paint.Style.FILL);
74a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        if (isInEditMode()) {
75a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            mDotPaint.setColor(0x646464);
76a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            mSliderColor = 0x888888;
77a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        } else {
78a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
79a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
80a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        }
81a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mPaint1.setStyle(Paint.Style.FILL);
82a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mPaint1.setAntiAlias(true);
83a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mPaint1.setFilterBitmap(true);
84a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
85a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mBitmap = Bitmap.createBitmap(64, 46, Bitmap.Config.ARGB_8888);
86a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        fillBitmap();
87a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
88a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
896125a082a2b5ddc0d34a5198c5a7e826bd77e202John Hoford    @Override
906125a082a2b5ddc0d34a5198c5a7e826bd77e202John Hoford    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
916125a082a2b5ddc0d34a5198c5a7e826bd77e202John Hoford        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
926125a082a2b5ddc0d34a5198c5a7e826bd77e202John Hoford    }
936125a082a2b5ddc0d34a5198c5a7e826bd77e202John Hoford
94a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    void fillBitmap() {
95a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        int w = mBitmap.getWidth();
96a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        int h = mBitmap.getHeight();
97a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        int[] buff = new int[w * h];
98a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        float[] hsv = new float[3];
99a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        hsv[0] = mHSVO[0];
100a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        for (int i = 0; i < w * h; i++) {
101a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            float sat = (i % w) / (float) w;
102a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            float val = (w - i / w) / (float) w;
103a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            hsv[1] = sat;
104a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            hsv[2] = val;
105a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            buff[i] = Color.HSVToColor(hsv);
106a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        }
107a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mBitmap.setPixels(buff, 0, w, 0, 0, w, h);
108a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
109a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
110a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private void setUpColorPanel() {
111a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        updateDot();
112a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        updateDotPaint();
113a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        fillBitmap();
114a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
115a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
116a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
117a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
118a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    @Override
119a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    protected void onDraw(Canvas canvas) {
120a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        super.onDraw(canvas);
121a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        Rect r = canvas.getClipBounds();
122a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mRect.set(r);
123a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mRect.top += mBorder;
124a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mRect.bottom -= mBorder;
125a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mRect.left += mBorder;
126a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mRect.right -= mBorder;
127a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        canvas.drawBitmap(mBitmap, null, mRect, mPaint1);
128a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
129a900c0a7b4f3fd4797290428a97c48066a2689ebIan Rogers        if (!Float.isNaN(mDotX)) {
130a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            canvas.drawCircle(mDotX, mDotY, mDotRadus, mDotPaint);
131a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        }
132a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
133a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
134a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
135a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    public boolean onDown(MotionEvent e) {
136a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        return true;
137a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
138a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
139a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    @Override
140a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    public boolean onTouchEvent(MotionEvent event) {
141a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
142a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
143a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford                (int) (mDotY + mDotRadus));
144a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        float x = event.getX();
145a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        float y = event.getY();
146a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
147a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        x = Math.max(Math.min(x, mWidth - mBorder), mBorder);
148a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        y = Math.max(Math.min(y, mHeight - mBorder), mBorder);
149a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mDotX = x;
150a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mDotY = y;
151a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        float sat = 1 - (mDotY - mBorder) / (mHeight - 2 * mBorder);
152a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        if (sat > 1) {
153a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            sat = 1;
154a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        }
155a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
156a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        float value = (mDotX - mBorder) / (mHeight - 2 * mBorder);
157a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mHSVO[2] = sat;
158a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mHSVO[1] = value;
159a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        notifyColorListeners(mHSVO);
160a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        updateDotPaint();
161a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
162a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford                (int) (mDotY + mDotRadus));
163a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
164a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        return true;
165a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
166a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
167a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    @Override
168a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
169a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mWidth = w;
170a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mHeight = h;
171a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mCtrY = h / 2f;
172a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mCtrX = w / 2f;
173a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
174a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        setUpColorPanel();
175a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
176a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
177a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
178a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private void updateDot() {
179a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
180a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        double hue = mHSVO[0];
181a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        double sat = mHSVO[1];
182a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        double val = mHSVO[2];
183a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        double opc = mHSVO[3];
184a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
185a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mDotX = (float) (mBorder + (mHeight - 2 * mBorder) * sat);
186a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mDotY = (float) ((1 - val) * (mHeight - 2 * mBorder) + mBorder);
187a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
188a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
189a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
190a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    private void updateDotPaint() {
191a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        int[] colors3 = new int[]{
192a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford                mSliderColor, mSliderColor, 0x66000000, 0};
193a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadus, colors3, new float[]{
194a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford                0, .3f, .31f, 1}, Shader.TileMode.CLAMP);
195a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mDotPaint.setShader(g);
196a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
197a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
198a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
199a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    @Override
200a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    public void setColor(float[] hsvo) {
201a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        if (hsvo[0] == mHSVO[0]
202a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford                && hsvo[1] == mHSVO[1]
203a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford                && hsvo[2] == mHSVO[2]) {
204a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            mHSVO[3] = hsvo[3]; // we don't update if color stays the same
205a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            return;
206a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        }
207a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length);
208a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
209a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        setUpColorPanel();
210a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        invalidate();
211a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
212a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        updateDot();
213a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        updateDotPaint();
214a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
215a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
216a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
217a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
218a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
219a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    public void notifyColorListeners(float[] hsv) {
220a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        for (ColorListener l : mColorListeners) {
221a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford            l.setColor(hsv);
222a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        }
223a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
224a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
225a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    public void addColorListener(ColorListener l) {
226a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mColorListeners.add(l);
227a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
228a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford
229a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    public void removeColorListener(ColorListener l) {
230a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford        mColorListeners.remove(l);
231a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford    }
232a4f38c0f8f70c998391780b672eea5d5e49277c7John Hoford}
233