1 /* 2 * Copyright (C) 2007 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.example.android.apis.graphics; 18 19 import android.os.Bundle; 20 import android.app.Dialog; 21 import android.content.Context; 22 import android.graphics.*; 23 import android.view.MotionEvent; 24 import android.view.View; 25 26 public class ColorPickerDialog extends Dialog { 27 28 public interface OnColorChangedListener { 29 void colorChanged(int color); 30 } 31 32 private OnColorChangedListener mListener; 33 private int mInitialColor; 34 35 private static class ColorPickerView extends View { 36 private Paint mPaint; 37 private Paint mCenterPaint; 38 private final int[] mColors; 39 private OnColorChangedListener mListener; 40 41 ColorPickerView(Context c, OnColorChangedListener l, int color) { 42 super(c); 43 mListener = l; 44 mColors = new int[] { 45 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF, 0xFF00FF00, 46 0xFFFFFF00, 0xFFFF0000 47 }; 48 Shader s = new SweepGradient(0, 0, mColors, null); 49 50 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 51 mPaint.setShader(s); 52 mPaint.setStyle(Paint.Style.STROKE); 53 mPaint.setStrokeWidth(32); 54 55 mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 56 mCenterPaint.setColor(color); 57 mCenterPaint.setStrokeWidth(5); 58 } 59 60 private boolean mTrackingCenter; 61 private boolean mHighlightCenter; 62 63 @Override 64 protected void onDraw(Canvas canvas) { 65 float r = CENTER_X - mPaint.getStrokeWidth()*0.5f; 66 67 canvas.translate(CENTER_X, CENTER_X); 68 69 canvas.drawOval(new RectF(-r, -r, r, r), mPaint); 70 canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint); 71 72 if (mTrackingCenter) { 73 int c = mCenterPaint.getColor(); 74 mCenterPaint.setStyle(Paint.Style.STROKE); 75 76 if (mHighlightCenter) { 77 mCenterPaint.setAlpha(0xFF); 78 } else { 79 mCenterPaint.setAlpha(0x80); 80 } 81 canvas.drawCircle(0, 0, 82 CENTER_RADIUS + mCenterPaint.getStrokeWidth(), 83 mCenterPaint); 84 85 mCenterPaint.setStyle(Paint.Style.FILL); 86 mCenterPaint.setColor(c); 87 } 88 } 89 90 @Override 91 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 92 setMeasuredDimension(CENTER_X*2, CENTER_Y*2); 93 } 94 95 private static final int CENTER_X = 100; 96 private static final int CENTER_Y = 100; 97 private static final int CENTER_RADIUS = 32; 98 99 private int floatToByte(float x) { 100 int n = java.lang.Math.round(x); 101 return n; 102 } 103 private int pinToByte(int n) { 104 if (n < 0) { 105 n = 0; 106 } else if (n > 255) { 107 n = 255; 108 } 109 return n; 110 } 111 112 private int ave(int s, int d, float p) { 113 return s + java.lang.Math.round(p * (d - s)); 114 } 115 116 private int interpColor(int colors[], float unit) { 117 if (unit <= 0) { 118 return colors[0]; 119 } 120 if (unit >= 1) { 121 return colors[colors.length - 1]; 122 } 123 124 float p = unit * (colors.length - 1); 125 int i = (int)p; 126 p -= i; 127 128 // now p is just the fractional part [0...1) and i is the index 129 int c0 = colors[i]; 130 int c1 = colors[i+1]; 131 int a = ave(Color.alpha(c0), Color.alpha(c1), p); 132 int r = ave(Color.red(c0), Color.red(c1), p); 133 int g = ave(Color.green(c0), Color.green(c1), p); 134 int b = ave(Color.blue(c0), Color.blue(c1), p); 135 136 return Color.argb(a, r, g, b); 137 } 138 139 private int rotateColor(int color, float rad) { 140 float deg = rad * 180 / 3.1415927f; 141 int r = Color.red(color); 142 int g = Color.green(color); 143 int b = Color.blue(color); 144 145 ColorMatrix cm = new ColorMatrix(); 146 ColorMatrix tmp = new ColorMatrix(); 147 148 cm.setRGB2YUV(); 149 tmp.setRotate(0, deg); 150 cm.postConcat(tmp); 151 tmp.setYUV2RGB(); 152 cm.postConcat(tmp); 153 154 final float[] a = cm.getArray(); 155 156 int ir = floatToByte(a[0] * r + a[1] * g + a[2] * b); 157 int ig = floatToByte(a[5] * r + a[6] * g + a[7] * b); 158 int ib = floatToByte(a[10] * r + a[11] * g + a[12] * b); 159 160 return Color.argb(Color.alpha(color), pinToByte(ir), 161 pinToByte(ig), pinToByte(ib)); 162 } 163 164 private static final float PI = 3.1415926f; 165 166 @Override 167 public boolean onTouchEvent(MotionEvent event) { 168 float x = event.getX() - CENTER_X; 169 float y = event.getY() - CENTER_Y; 170 boolean inCenter = java.lang.Math.sqrt(x*x + y*y) <= CENTER_RADIUS; 171 172 switch (event.getAction()) { 173 case MotionEvent.ACTION_DOWN: 174 mTrackingCenter = inCenter; 175 if (inCenter) { 176 mHighlightCenter = true; 177 invalidate(); 178 break; 179 } 180 case MotionEvent.ACTION_MOVE: 181 if (mTrackingCenter) { 182 if (mHighlightCenter != inCenter) { 183 mHighlightCenter = inCenter; 184 invalidate(); 185 } 186 } else { 187 float angle = (float)java.lang.Math.atan2(y, x); 188 // need to turn angle [-PI ... PI] into unit [0....1] 189 float unit = angle/(2*PI); 190 if (unit < 0) { 191 unit += 1; 192 } 193 mCenterPaint.setColor(interpColor(mColors, unit)); 194 invalidate(); 195 } 196 break; 197 case MotionEvent.ACTION_UP: 198 if (mTrackingCenter) { 199 if (inCenter) { 200 mListener.colorChanged(mCenterPaint.getColor()); 201 } 202 mTrackingCenter = false; // so we draw w/o halo 203 invalidate(); 204 } 205 break; 206 } 207 return true; 208 } 209 } 210 211 public ColorPickerDialog(Context context, 212 OnColorChangedListener listener, 213 int initialColor) { 214 super(context); 215 216 mListener = listener; 217 mInitialColor = initialColor; 218 } 219 220 @Override 221 protected void onCreate(Bundle savedInstanceState) { 222 super.onCreate(savedInstanceState); 223 OnColorChangedListener l = new OnColorChangedListener() { 224 public void colorChanged(int color) { 225 mListener.colorChanged(color); 226 dismiss(); 227 } 228 }; 229 230 setContentView(new ColorPickerView(getContext(), l, mInitialColor)); 231 setTitle("Pick a Color"); 232 } 233 } 234