1/*
2 * Copyright (C) 2013 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
17package com.android.gallery3d.filtershow.colorpicker;
18
19import android.content.Context;
20import android.graphics.Bitmap;
21import android.graphics.BitmapShader;
22import android.graphics.Canvas;
23import android.graphics.Color;
24import android.graphics.LinearGradient;
25import android.graphics.Paint;
26import android.graphics.RadialGradient;
27import android.graphics.RectF;
28import android.graphics.Shader;
29import android.util.AttributeSet;
30import android.util.DisplayMetrics;
31import android.view.MotionEvent;
32import android.view.View;
33
34import com.android.gallery3d.R;
35
36import java.util.ArrayList;
37
38public class ColorHueView extends View implements ColorListener {
39
40    private float mWidth;
41
42    private Paint mLinePaint1;
43    private Paint mLinePaint2;
44    private Paint mPaint = new Paint();
45    private float mHeight;
46    private Paint mDotPaint;
47    private int mBgcolor = 0;
48    Bitmap mBitmap;
49    private float mDotRadius;
50    private float mBorder;
51
52    private float[] mHSVO = {0.f,0.f,0.f,0.f};
53    private int mSliderColor;
54    private float mDotX = mBorder;
55    private float mDotY = mBorder;
56
57    public final static float DOT_SIZE = 20;
58    public final static float BORDER_SIZE = 20;
59    RectF mRect = new RectF();
60    int[] mTmpBuff;
61    float[] mTmpHSV = new float[3];
62    private Paint mCheckPaint;
63
64    public ColorHueView(Context ctx, AttributeSet attrs) {
65        super(ctx, attrs);
66        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
67        float mDpToPix = metrics.density;
68        mDotRadius = DOT_SIZE * mDpToPix;
69        mBorder = BORDER_SIZE * mDpToPix;
70
71        mDotPaint = new Paint();
72
73        mDotPaint.setStyle(Paint.Style.FILL);
74        mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
75        mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
76
77
78        mLinePaint1 = new Paint();
79        mLinePaint1.setColor(Color.GRAY);
80        mLinePaint2 = new Paint();
81        mLinePaint2.setColor(mSliderColor);
82        mLinePaint2.setStrokeWidth(4);
83
84        mBitmap = Bitmap.createBitmap(256, 2, Bitmap.Config.ARGB_8888);
85        mTmpBuff = new int[mBitmap.getWidth() * mBitmap.getHeight()];
86        mPaint.setAntiAlias(true);
87        mPaint.setFilterBitmap(true);
88        fillBitmap();
89        makeCheckPaint();
90    }
91
92    void fillBitmap() {
93        int w = mBitmap.getWidth();
94        int h = mBitmap.getHeight();
95
96        for (int x = 0; x < w; x++) {
97            float hue = 360 * (x) / (float) w;
98
99            mTmpHSV[0] = hue;
100            mTmpHSV[1] = 1;
101            mTmpHSV[2] = 1;
102            int color = Color.HSVToColor(mTmpHSV);
103            mTmpBuff[x] = color;
104            mTmpBuff[x + w] = color;
105
106        }
107
108        mBitmap.setPixels(mTmpBuff, 0, w, 0, 0, w, h);
109    }
110
111
112    public boolean onDown(MotionEvent e) {
113        return true;
114    }
115
116    @Override
117    public boolean onTouchEvent(MotionEvent event) {
118        float ox = mDotX;
119        float oy = mDotY;
120
121        float x = event.getX();
122        float y = event.getY();
123
124        mDotX = x;
125
126        if (mDotX < mBorder) {
127            mDotX = mBorder;
128        }
129
130        if (mDotX > mWidth - mBorder) {
131            mDotX = mWidth - mBorder;
132        }
133        mHSVO[0] = 360 * (mDotX - mBorder) / (mWidth - mBorder * 2);
134        notifyColorListeners(mHSVO);
135        setupButton();
136        fillBitmap();
137//        invalidate((int) (ox - mDotRadius), (int) (oy - mDotRadius), (int) (ox + mDotRadius),
138//                (int) (oy + mDotRadius));
139//        invalidate(
140//                (int) (mDotX - mDotRadius), (int) (mDotY - mDotRadius), (int) (mDotX + mDotRadius),
141//                (int) (mDotY + mDotRadius));
142        invalidate();
143
144        return true;
145    }
146
147    private void setupButton() {
148        float pos = mHSVO[0] / 360 * (mWidth - mBorder * 2);
149        mDotX = pos + mBorder;
150
151        int[] colors3 = new int[]{
152                mSliderColor, mSliderColor, 0x66000000, 0};
153        RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadius, colors3, new float[]{
154                0, .3f, .31f, 1}, Shader.TileMode.CLAMP);
155        mDotPaint.setShader(g);
156    }
157
158    @Override
159    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
160        mWidth = w;
161        mHeight = h;
162        mDotY = mHeight / 2;
163        setupButton();
164    }
165
166
167    @Override
168    protected void onDraw(Canvas canvas) {
169        super.onDraw(canvas);
170        canvas.drawColor(mBgcolor);
171
172        mRect.left = mBorder;
173        mRect.right = mWidth - mBorder;
174        mRect.top = 0;
175        mRect.bottom = mHeight;
176        canvas.drawRect(mRect,mCheckPaint);
177        canvas.drawBitmap(mBitmap, null, mRect, mPaint);
178
179
180        canvas.drawLine(mDotX, mDotY, mWidth - mBorder, mDotY, mLinePaint1);
181        canvas.drawLine(mBorder, mDotY, mDotX, mDotY, mLinePaint2);
182        if (!Float.isNaN(mDotX)) {
183            canvas.drawCircle(mDotX, mDotY, mDotRadius, mDotPaint);
184        }
185    }
186
187    private void makeCheckPaint(){
188        int block = 16;
189        int checkdim = block*2;
190        int[] colors = new int[checkdim * checkdim];
191        for (int i = 0; i < colors.length; i++) {
192            int y = i / (checkdim * block);
193            int x = (i / block) % 2;
194            colors[i] = (x == y) ? 0xFFAAAAAA : 0xFF444444;
195        }
196        Bitmap bitmap = Bitmap.createBitmap(colors, 16, 16, Bitmap.Config.ARGB_8888);
197        BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
198        mCheckPaint = new Paint();
199        mCheckPaint.setShader(bs);
200    }
201
202    @Override
203    public void setColor(float[] hsv) {
204        System.arraycopy(hsv, 0, mHSVO, 0, mHSVO.length);
205        fillBitmap();
206        setupButton();
207        invalidate();
208    }
209
210    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
211
212    public void notifyColorListeners(float[] hsvo) {
213        for (ColorListener l : mColorListeners) {
214            l.setColor(hsvo);
215        }
216    }
217
218    public void addColorListener(ColorListener l) {
219        mColorListeners.add(l);
220    }
221
222    public void removeColorListener(ColorListener l) {
223        mColorListeners.remove(l);
224    }
225}
226