blob: fb8b4fcb427372f2d651da32ce4fcf5c9775e8b3 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.gallery3d.filtershow.colorpicker;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import com.android.gallery3d.R;
import java.util.ArrayList;
public class ColorSVRectView extends View implements ColorListener {
private float mDpToPix;
private float mCtrY = 100;
private Paint mPaint1;
private float mCtrX = 100;
private Paint mDotPaint = new Paint();
private float mDotRadus;
private float mBorder;
private float mDotX = Float.NaN;
private float mDotY;
private int mSliderColor = 0xFF33B5E5;
private float[] mHSVO = new float[]{0, 1, 1, 1};
RectF mRect = new RectF();
private int mWidth;
private int mHeight;
public final static float DOT_SIZE = 20;
public final static float BORDER_SIZE = 20;
Bitmap mBitmap;
public ColorSVRectView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
mDpToPix = metrics.density;
mDotRadus = DOT_SIZE * mDpToPix;
mBorder = BORDER_SIZE * mDpToPix;
mPaint1 = new Paint();
mDotPaint.setStyle(Paint.Style.FILL);
if (isInEditMode()) {
mDotPaint.setColor(0x646464);
mSliderColor = 0x888888;
} else {
mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
}
mPaint1.setStyle(Paint.Style.FILL);
mPaint1.setAntiAlias(true);
mPaint1.setFilterBitmap(true);
mBitmap = Bitmap.createBitmap(64, 46, Bitmap.Config.ARGB_8888);
fillBitmap();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
void fillBitmap() {
int w = mBitmap.getWidth();
int h = mBitmap.getHeight();
int[] buff = new int[w * h];
float[] hsv = new float[3];
hsv[0] = mHSVO[0];
for (int i = 0; i < w * h; i++) {
float sat = (i % w) / (float) w;
float val = (w - i / w) / (float) w;
hsv[1] = sat;
hsv[2] = val;
buff[i] = Color.HSVToColor(hsv);
}
mBitmap.setPixels(buff, 0, w, 0, 0, w, h);
}
private void setUpColorPanel() {
updateDot();
updateDotPaint();
fillBitmap();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect r = canvas.getClipBounds();
mRect.set(r);
mRect.top += mBorder;
mRect.bottom -= mBorder;
mRect.left += mBorder;
mRect.right -= mBorder;
canvas.drawBitmap(mBitmap, null, mRect, mPaint1);
if (mDotX != Float.NaN) {
canvas.drawCircle(mDotX, mDotY, mDotRadus, mDotPaint);
}
}
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
(int) (mDotY + mDotRadus));
float x = event.getX();
float y = event.getY();
x = Math.max(Math.min(x, mWidth - mBorder), mBorder);
y = Math.max(Math.min(y, mHeight - mBorder), mBorder);
mDotX = x;
mDotY = y;
float sat = 1 - (mDotY - mBorder) / (mHeight - 2 * mBorder);
if (sat > 1) {
sat = 1;
}
float value = (mDotX - mBorder) / (mHeight - 2 * mBorder);
mHSVO[2] = sat;
mHSVO[1] = value;
notifyColorListeners(mHSVO);
updateDotPaint();
invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
(int) (mDotY + mDotRadus));
return true;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mWidth = w;
mHeight = h;
mCtrY = h / 2f;
mCtrX = w / 2f;
setUpColorPanel();
}
private void updateDot() {
double hue = mHSVO[0];
double sat = mHSVO[1];
double val = mHSVO[2];
double opc = mHSVO[3];
mDotX = (float) (mBorder + (mHeight - 2 * mBorder) * sat);
mDotY = (float) ((1 - val) * (mHeight - 2 * mBorder) + mBorder);
}
private void updateDotPaint() {
int[] colors3 = new int[]{
mSliderColor, mSliderColor, 0x66000000, 0};
RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadus, colors3, new float[]{
0, .3f, .31f, 1}, Shader.TileMode.CLAMP);
mDotPaint.setShader(g);
}
@Override
public void setColor(float[] hsvo) {
if (hsvo[0] == mHSVO[0]
&& hsvo[1] == mHSVO[1]
&& hsvo[2] == mHSVO[2]) {
mHSVO[3] = hsvo[3]; // we don't update if color stays the same
return;
}
System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length);
setUpColorPanel();
invalidate();
updateDot();
updateDotPaint();
}
ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
public void notifyColorListeners(float[] hsv) {
for (ColorListener l : mColorListeners) {
l.setColor(hsv);
}
}
public void addColorListener(ColorListener l) {
mColorListeners.add(l);
}
public void removeColorListener(ColorListener l) {
mColorListeners.remove(l);
}
}