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.content.res.Resources;
21import android.graphics.Bitmap;
22import android.graphics.BitmapShader;
23import android.graphics.Canvas;
24import android.graphics.Color;
25import android.graphics.LinearGradient;
26import android.graphics.Paint;
27import android.graphics.RadialGradient;
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 ColorOpacityView extends View implements ColorListener {
39
40    private float mRadius;
41    private float mWidth;
42    private Paint mBarPaint1;
43    private Paint mLinePaint1;
44    private Paint mLinePaint2;
45    private Paint mCheckPaint;
46
47    private float mHeight;
48    private Paint mDotPaint;
49    private int mBgcolor = 0;
50
51    private float mDotRadius;
52    private float mBorder;
53
54    private float[] mHSVO = new float[4];
55    private int mSliderColor;
56    private float mDotX = mBorder;
57    private float mDotY = mBorder;
58    private final static float DOT_SIZE = ColorHueView.DOT_SIZE;
59    public final static float BORDER_SIZE = 20;;
60    private  int mCheckDim = 8;
61    public ColorOpacityView(Context ctx, AttributeSet attrs) {
62        super(ctx, attrs);
63        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
64        float mDpToPix = metrics.density;
65        mDotRadius = DOT_SIZE * mDpToPix;
66        mBorder = BORDER_SIZE * mDpToPix;
67        mBarPaint1 = new Paint();
68
69        mDotPaint = new Paint();
70
71        mDotPaint.setStyle(Paint.Style.FILL);
72        Resources res = ctx.getResources();
73        mCheckDim = res.getDimensionPixelSize(R.dimen.draw_color_check_dim);
74        mDotPaint.setColor(res.getColor(R.color.slider_dot_color));
75        mSliderColor = res.getColor(R.color.slider_line_color);
76
77        mBarPaint1.setStyle(Paint.Style.FILL);
78
79        mLinePaint1 = new Paint();
80        mLinePaint1.setColor(Color.GRAY);
81        mLinePaint2 = new Paint();
82        mLinePaint2.setColor(mSliderColor);
83        mLinePaint2.setStrokeWidth(4);
84
85        makeCheckPaint();
86    }
87
88    private void makeCheckPaint(){
89        int imgdim = mCheckDim*2;
90        int[] colors = new int[imgdim * imgdim];
91        for (int i = 0; i < colors.length; i++) {
92            int y = i / (imgdim * mCheckDim);
93            int x = (i / mCheckDim) % 2;
94            colors[i] = (x == y) ? 0xFFAAAAAA : 0xFF444444;
95        }
96        Bitmap bitmap = Bitmap.createBitmap(colors, imgdim, imgdim, Bitmap.Config.ARGB_8888);
97        BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
98        mCheckPaint = new Paint();
99        mCheckPaint.setShader(bs);
100    }
101
102    public boolean onDown(MotionEvent e) {
103        return true;
104    }
105
106    @Override
107    public boolean onTouchEvent(MotionEvent event) {
108        float ox = mDotX;
109        float oy = mDotY;
110
111        float x = event.getX();
112        float y = event.getY();
113
114        mDotX = x;
115
116        if (mDotX < mBorder) {
117            mDotX = mBorder;
118        }
119
120        if (mDotX > mWidth - mBorder) {
121            mDotX = mWidth - mBorder;
122        }
123        mHSVO[3] = (mDotX - mBorder) / (mWidth - mBorder * 2);
124        notifyColorListeners(mHSVO);
125        setupButton();
126        invalidate((int) (ox - mDotRadius), (int) (oy - mDotRadius), (int) (ox + mDotRadius),
127                (int) (oy + mDotRadius));
128        invalidate(
129                (int) (mDotX - mDotRadius), (int) (mDotY - mDotRadius), (int) (mDotX + mDotRadius),
130                (int) (mDotY + mDotRadius));
131
132        return true;
133    }
134
135    private void setupButton() {
136        float pos = mHSVO[3] * (mWidth - mBorder * 2);
137        mDotX = pos + mBorder;
138
139        int[] colors3 = new int[] {
140                mSliderColor, mSliderColor, 0x66000000, 0 };
141        RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadius, colors3, new float[] {
142                0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
143        mDotPaint.setShader(g);
144    }
145
146    @Override
147    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
148        mWidth = w;
149        mHeight = h;
150        mDotY = mHeight / 2;
151        updatePaint();
152        setupButton();
153    }
154
155    private void updatePaint() {
156
157        int color2 = Color.HSVToColor(mHSVO);
158        int color1 = color2 & 0xFFFFFF;
159
160        Shader sg = new LinearGradient(
161                mBorder, mBorder, mWidth - mBorder, mBorder, color1, color2, Shader.TileMode.CLAMP);
162        mBarPaint1.setShader(sg);
163
164    }
165
166    @Override
167    protected void onDraw(Canvas canvas) {
168        super.onDraw(canvas);
169        canvas.drawColor(mBgcolor);
170        canvas.drawRect(mBorder, 0, mWidth - mBorder, mHeight, mCheckPaint);
171        canvas.drawRect(mBorder, 0, mWidth - mBorder, mHeight, mBarPaint1);
172        canvas.drawLine(mDotX, mDotY, mWidth - mBorder, mDotY, mLinePaint1);
173        canvas.drawLine(mBorder, mDotY, mDotX, mDotY, mLinePaint2);
174        if (!Float.isNaN(mDotX)) {
175            canvas.drawCircle(mDotX, mDotY, mDotRadius, mDotPaint);
176        }
177    }
178
179    @Override
180    public void setColor(float[] hsv) {
181        System.arraycopy(hsv, 0, mHSVO, 0, mHSVO.length);
182
183        updatePaint();
184        setupButton();
185        invalidate();
186    }
187
188    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
189
190    public void notifyColorListeners(float[] hsvo) {
191        for (ColorListener l : mColorListeners) {
192            l.setColor(hsvo);
193        }
194    }
195
196    public void addColorListener(ColorListener l) {
197        mColorListeners.add(l);
198    }
199
200    public void removeColorListener(ColorListener l) {
201        mColorListeners.remove(l);
202    }
203}
204