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.Canvas; 22import android.graphics.Color; 23import android.graphics.LinearGradient; 24import android.graphics.Paint; 25import android.graphics.RadialGradient; 26import android.graphics.Rect; 27import android.graphics.RectF; 28import android.graphics.Shader; 29import android.graphics.SweepGradient; 30import android.util.AttributeSet; 31import android.util.DisplayMetrics; 32import android.view.MotionEvent; 33import android.view.View; 34 35import com.android.gallery3d.R; 36 37import java.util.ArrayList; 38 39public class ColorSVRectView extends View implements ColorListener { 40 private float mDpToPix; 41 42 private float mCtrY = 100; 43 private Paint mPaint1; 44 45 private float mCtrX = 100; 46 private Paint mDotPaint = new Paint(); 47 private float mDotRadus; 48 private float mBorder; 49 50 private float mDotX = Float.NaN; 51 private float mDotY; 52 private int mSliderColor = 0xFF33B5E5; 53 private float[] mHSVO = new float[]{0, 1, 1, 1}; 54 RectF mRect = new RectF(); 55 56 private int mWidth; 57 private int mHeight; 58 public final static float DOT_SIZE = 20; 59 public final static float BORDER_SIZE = 20; 60 Bitmap mBitmap; 61 62 public ColorSVRectView(Context ctx, AttributeSet attrs) { 63 super(ctx, attrs); 64 65 DisplayMetrics metrics = ctx.getResources().getDisplayMetrics(); 66 mDpToPix = metrics.density; 67 mDotRadus = DOT_SIZE * mDpToPix; 68 mBorder = BORDER_SIZE * mDpToPix; 69 70 mPaint1 = new Paint(); 71 72 73 mDotPaint.setStyle(Paint.Style.FILL); 74 if (isInEditMode()) { 75 mDotPaint.setColor(0x646464); 76 mSliderColor = 0x888888; 77 } else { 78 mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color)); 79 mSliderColor = ctx.getResources().getColor(R.color.slider_line_color); 80 } 81 mPaint1.setStyle(Paint.Style.FILL); 82 mPaint1.setAntiAlias(true); 83 mPaint1.setFilterBitmap(true); 84 85 mBitmap = Bitmap.createBitmap(64, 46, Bitmap.Config.ARGB_8888); 86 fillBitmap(); 87 } 88 89 @Override 90 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 91 super.onMeasure(widthMeasureSpec, widthMeasureSpec); 92 } 93 94 void fillBitmap() { 95 int w = mBitmap.getWidth(); 96 int h = mBitmap.getHeight(); 97 int[] buff = new int[w * h]; 98 float[] hsv = new float[3]; 99 hsv[0] = mHSVO[0]; 100 for (int i = 0; i < w * h; i++) { 101 float sat = (i % w) / (float) w; 102 float val = (w - i / w) / (float) w; 103 hsv[1] = sat; 104 hsv[2] = val; 105 buff[i] = Color.HSVToColor(hsv); 106 } 107 mBitmap.setPixels(buff, 0, w, 0, 0, w, h); 108 } 109 110 private void setUpColorPanel() { 111 updateDot(); 112 updateDotPaint(); 113 fillBitmap(); 114 115 } 116 117 118 @Override 119 protected void onDraw(Canvas canvas) { 120 super.onDraw(canvas); 121 Rect r = canvas.getClipBounds(); 122 mRect.set(r); 123 mRect.top += mBorder; 124 mRect.bottom -= mBorder; 125 mRect.left += mBorder; 126 mRect.right -= mBorder; 127 canvas.drawBitmap(mBitmap, null, mRect, mPaint1); 128 129 if (!Float.isNaN(mDotX)) { 130 canvas.drawCircle(mDotX, mDotY, mDotRadus, mDotPaint); 131 } 132 } 133 134 135 public boolean onDown(MotionEvent e) { 136 return true; 137 } 138 139 @Override 140 public boolean onTouchEvent(MotionEvent event) { 141 142 invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus), 143 (int) (mDotY + mDotRadus)); 144 float x = event.getX(); 145 float y = event.getY(); 146 147 x = Math.max(Math.min(x, mWidth - mBorder), mBorder); 148 y = Math.max(Math.min(y, mHeight - mBorder), mBorder); 149 mDotX = x; 150 mDotY = y; 151 float sat = 1 - (mDotY - mBorder) / (mHeight - 2 * mBorder); 152 if (sat > 1) { 153 sat = 1; 154 } 155 156 float value = (mDotX - mBorder) / (mHeight - 2 * mBorder); 157 mHSVO[2] = sat; 158 mHSVO[1] = value; 159 notifyColorListeners(mHSVO); 160 updateDotPaint(); 161 invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus), 162 (int) (mDotY + mDotRadus)); 163 164 return true; 165 } 166 167 @Override 168 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 169 mWidth = w; 170 mHeight = h; 171 mCtrY = h / 2f; 172 mCtrX = w / 2f; 173 174 setUpColorPanel(); 175 } 176 177 178 private void updateDot() { 179 180 double hue = mHSVO[0]; 181 double sat = mHSVO[1]; 182 double val = mHSVO[2]; 183 double opc = mHSVO[3]; 184 185 mDotX = (float) (mBorder + (mHeight - 2 * mBorder) * sat); 186 mDotY = (float) ((1 - val) * (mHeight - 2 * mBorder) + mBorder); 187 188 } 189 190 private void updateDotPaint() { 191 int[] colors3 = new int[]{ 192 mSliderColor, mSliderColor, 0x66000000, 0}; 193 RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadus, colors3, new float[]{ 194 0, .3f, .31f, 1}, Shader.TileMode.CLAMP); 195 mDotPaint.setShader(g); 196 197 } 198 199 @Override 200 public void setColor(float[] hsvo) { 201 if (hsvo[0] == mHSVO[0] 202 && hsvo[1] == mHSVO[1] 203 && hsvo[2] == mHSVO[2]) { 204 mHSVO[3] = hsvo[3]; // we don't update if color stays the same 205 return; 206 } 207 System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length); 208 209 setUpColorPanel(); 210 invalidate(); 211 212 updateDot(); 213 updateDotPaint(); 214 215 } 216 217 ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>(); 218 219 public void notifyColorListeners(float[] hsv) { 220 for (ColorListener l : mColorListeners) { 221 l.setColor(hsv); 222 } 223 } 224 225 public void addColorListener(ColorListener l) { 226 mColorListeners.add(l); 227 } 228 229 public void removeColorListener(ColorListener l) { 230 mColorListeners.remove(l); 231 } 232} 233