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 17 package com.android.gallery3d.filtershow.colorpicker; 18 19 import android.content.Context; 20 import android.graphics.Bitmap; 21 import android.graphics.Canvas; 22 import android.graphics.Color; 23 import android.graphics.LinearGradient; 24 import android.graphics.Paint; 25 import android.graphics.RadialGradient; 26 import android.graphics.Rect; 27 import android.graphics.RectF; 28 import android.graphics.Shader; 29 import android.graphics.SweepGradient; 30 import android.util.AttributeSet; 31 import android.util.DisplayMetrics; 32 import android.view.MotionEvent; 33 import android.view.View; 34 35 import com.android.gallery3d.R; 36 37 import java.util.ArrayList; 38 39 public 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 (mDotX != Float.NaN) { 130 131 canvas.drawCircle(mDotX, mDotY, mDotRadus, mDotPaint); 132 } 133 } 134 135 136 public boolean onDown(MotionEvent e) { 137 return true; 138 } 139 140 @Override 141 public boolean onTouchEvent(MotionEvent event) { 142 143 invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus), 144 (int) (mDotY + mDotRadus)); 145 float x = event.getX(); 146 float y = event.getY(); 147 148 x = Math.max(Math.min(x, mWidth - mBorder), mBorder); 149 y = Math.max(Math.min(y, mHeight - mBorder), mBorder); 150 mDotX = x; 151 mDotY = y; 152 float sat = 1 - (mDotY - mBorder) / (mHeight - 2 * mBorder); 153 if (sat > 1) { 154 sat = 1; 155 } 156 157 float value = (mDotX - mBorder) / (mHeight - 2 * mBorder); 158 mHSVO[2] = sat; 159 mHSVO[1] = value; 160 notifyColorListeners(mHSVO); 161 updateDotPaint(); 162 invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus), 163 (int) (mDotY + mDotRadus)); 164 165 return true; 166 } 167 168 @Override 169 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 170 mWidth = w; 171 mHeight = h; 172 mCtrY = h / 2f; 173 mCtrX = w / 2f; 174 175 setUpColorPanel(); 176 } 177 178 179 private void updateDot() { 180 181 double hue = mHSVO[0]; 182 double sat = mHSVO[1]; 183 double val = mHSVO[2]; 184 double opc = mHSVO[3]; 185 186 mDotX = (float) (mBorder + (mHeight - 2 * mBorder) * sat); 187 mDotY = (float) ((1 - val) * (mHeight - 2 * mBorder) + mBorder); 188 189 } 190 191 private void updateDotPaint() { 192 int[] colors3 = new int[]{ 193 mSliderColor, mSliderColor, 0x66000000, 0}; 194 RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadus, colors3, new float[]{ 195 0, .3f, .31f, 1}, Shader.TileMode.CLAMP); 196 mDotPaint.setShader(g); 197 198 } 199 200 @Override 201 public void setColor(float[] hsvo) { 202 if (hsvo[0] == mHSVO[0] 203 && hsvo[1] == mHSVO[1] 204 && hsvo[2] == mHSVO[2]) { 205 mHSVO[3] = hsvo[3]; // we don't update if color stays the same 206 return; 207 } 208 System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length); 209 210 setUpColorPanel(); 211 invalidate(); 212 213 updateDot(); 214 updateDotPaint(); 215 216 } 217 218 ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>(); 219 220 public void notifyColorListeners(float[] hsv) { 221 for (ColorListener l : mColorListeners) { 222 l.setColor(hsv); 223 } 224 } 225 226 public void addColorListener(ColorListener l) { 227 mColorListeners.add(l); 228 } 229 230 public void removeColorListener(ColorListener l) { 231 mColorListeners.remove(l); 232 } 233 } 234