0
|
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 /*
|
|
18 * 090408
|
|
19 * Keith Wiley
|
|
20 * kwiley@keithwiley.com
|
|
21 * http://keithwiley.com
|
|
22 *
|
|
23 * UberColorPickerDialog v1.1
|
|
24 *
|
|
25 * This color picker was implemented as a (significant) extension of the
|
|
26 * ColorPickerDialog class provided in the Android API Demos. You are free
|
|
27 * to drop it unchanged into your own projects or to modify it as you see
|
|
28 * fit. I would appreciate it if this comment block were let intact,
|
|
29 * merely for credit's sake.
|
|
30 *
|
|
31 * Enjoy!
|
|
32 */
|
|
33
|
|
34 package com.five_ten_sg.connectbot.util;
|
|
35
|
|
36 import android.app.Dialog;
|
|
37 import android.content.Context;
|
|
38 import android.graphics.Bitmap;
|
|
39 import android.graphics.Canvas;
|
|
40 import android.graphics.Color;
|
|
41 import android.graphics.ColorMatrix;
|
|
42 import android.graphics.ComposeShader;
|
|
43 import android.graphics.Paint;
|
|
44 import android.graphics.PorterDuff;
|
|
45 import android.graphics.PorterDuffXfermode;
|
|
46 import android.graphics.RadialGradient;
|
|
47 import android.graphics.Rect;
|
|
48 import android.graphics.RectF;
|
|
49 import android.graphics.Shader;
|
|
50 import android.graphics.SweepGradient;
|
|
51 import android.graphics.drawable.GradientDrawable;
|
|
52 import android.graphics.drawable.GradientDrawable.Orientation;
|
|
53 import android.os.Bundle;
|
|
54 import android.util.DisplayMetrics;
|
|
55 import android.util.FloatMath;
|
|
56 import android.view.MotionEvent;
|
|
57 import android.view.View;
|
|
58
|
|
59 /**
|
|
60 * UberColorPickerDialog is a seriously enhanced version of the UberColorPickerDialog
|
|
61 * class provided in the Android API Demos.<p>
|
|
62 *
|
|
63 * NOTE (from Kenny Root): This is a VERY slimmed down version custom for ConnectBot.
|
|
64 * Visit Keith's site for the full version at the URL listed in the author line.<p>
|
|
65 *
|
|
66 * @author Keith Wiley, kwiley@keithwiley.com, http://keithwiley.com
|
|
67 */
|
|
68 public class UberColorPickerDialog extends Dialog {
|
|
69 private final OnColorChangedListener mListener;
|
|
70 private final int mInitialColor;
|
|
71
|
|
72 /**
|
|
73 * Callback to the creator of the dialog, informing the creator of a new color and notifying that the dialog is about to dismiss.
|
|
74 */
|
|
75 public interface OnColorChangedListener {
|
|
76 void colorChanged(int color);
|
|
77 }
|
|
78
|
|
79 /**
|
|
80 * Ctor
|
|
81 * @param context
|
|
82 * @param listener
|
|
83 * @param initialColor
|
|
84 * @param showTitle If true, a title is shown across the top of the dialog. If false a toast is shown instead.
|
|
85 */
|
|
86 public UberColorPickerDialog(Context context,
|
|
87 OnColorChangedListener listener,
|
|
88 int initialColor) {
|
|
89 super(context);
|
|
90 mListener = listener;
|
|
91 mInitialColor = initialColor;
|
|
92 }
|
|
93
|
|
94 /**
|
|
95 * Activity entry point
|
|
96 */
|
|
97 @Override
|
|
98 protected void onCreate(Bundle savedInstanceState) {
|
|
99 super.onCreate(savedInstanceState);
|
|
100 OnColorChangedListener l = new OnColorChangedListener() {
|
|
101 public void colorChanged(int color) {
|
|
102 mListener.colorChanged(color);
|
|
103 dismiss();
|
|
104 }
|
|
105 };
|
|
106 DisplayMetrics dm = new DisplayMetrics();
|
|
107 getWindow().getWindowManager().getDefaultDisplay().getMetrics(dm);
|
|
108 int screenWidth = dm.widthPixels;
|
|
109 int screenHeight = dm.heightPixels;
|
|
110 setTitle("Pick a color (try the trackball)");
|
|
111
|
|
112 try {
|
|
113 setContentView(new ColorPickerView(getContext(), l, screenWidth, screenHeight, mInitialColor));
|
|
114 }
|
|
115 catch (Exception e) {
|
|
116 //There is currently only one kind of ctor exception, that where no methods are enabled.
|
|
117 dismiss(); //This doesn't work! The dialog is still shown (its title at least, the layout is empty from the exception being thrown). <sigh>
|
|
118 }
|
|
119 }
|
|
120
|
|
121 /**
|
|
122 * ColorPickerView is the meat of this color picker (as opposed to the enclosing class).
|
|
123 * All the heavy lifting is done directly by this View subclass.
|
|
124 * <P>
|
|
125 * You can enable/disable whichever color chooser methods you want by modifying the ENABLED_METHODS switches. They *should*
|
|
126 * do all the work required to properly enable/disable methods without losing track of what goes with what and what maps to what.
|
|
127 * <P>
|
|
128 * If you add a new color chooser method, do a text search for "NEW_METHOD_WORK_NEEDED_HERE". That tag indicates all
|
|
129 * the locations in the code that will have to be amended in order to properly add a new color chooser method.
|
|
130 * I highly recommend adding new methods to the end of the list. If you want to try to reorder the list, you're on your own.
|
|
131 */
|
|
132 private static class ColorPickerView extends View {
|
|
133 private static int SWATCH_WIDTH = 95;
|
|
134 private static final int SWATCH_HEIGHT = 60;
|
|
135
|
|
136 private static int PALETTE_POS_X = 0;
|
|
137 private static int PALETTE_POS_Y = SWATCH_HEIGHT;
|
|
138 private static final int PALETTE_DIM = SWATCH_WIDTH * 2;
|
|
139 private static final int PALETTE_RADIUS = PALETTE_DIM / 2;
|
|
140 private static final int PALETTE_CENTER_X = PALETTE_RADIUS;
|
|
141 private static final int PALETTE_CENTER_Y = PALETTE_RADIUS;
|
|
142
|
|
143 private static final int SLIDER_THICKNESS = 40;
|
|
144
|
|
145 private static int VIEW_DIM_X = PALETTE_DIM;
|
|
146 private static int VIEW_DIM_Y = SWATCH_HEIGHT;
|
|
147
|
|
148 //NEW_METHOD_WORK_NEEDED_HERE
|
|
149 private static final int METHOD_HS_V_PALETTE = 0;
|
|
150
|
|
151 //NEW_METHOD_WORK_NEEDED_HERE
|
|
152 //Add a new entry to the list for each controller in the new method
|
|
153 private static final int TRACKED_NONE = -1; //No object on screen is currently being tracked
|
|
154 private static final int TRACK_SWATCH_OLD = 10;
|
|
155 private static final int TRACK_SWATCH_NEW = 11;
|
|
156 private static final int TRACK_HS_PALETTE = 30;
|
|
157 private static final int TRACK_VER_VALUE_SLIDER = 31;
|
|
158
|
|
159 private static final int TEXT_SIZE = 12;
|
|
160 private static int[] TEXT_HSV_POS = new int[2];
|
|
161 private static int[] TEXT_RGB_POS = new int[2];
|
|
162 private static int[] TEXT_YUV_POS = new int[2];
|
|
163 private static int[] TEXT_HEX_POS = new int[2];
|
|
164
|
|
165 private static final float PI = 3.141592653589793f;
|
|
166
|
|
167 private int mMethod = METHOD_HS_V_PALETTE;
|
|
168 private int mTracking = TRACKED_NONE; //What object on screen is currently being tracked for movement
|
|
169
|
|
170 //Zillions of persistant Paint objecs for drawing the View
|
|
171
|
|
172 private Paint mSwatchOld, mSwatchNew;
|
|
173
|
|
174 //NEW_METHOD_WORK_NEEDED_HERE
|
|
175 //Add Paints to represent the palettes of the new method's UI controllers
|
|
176 private Paint mOvalHueSat;
|
|
177
|
|
178 private Bitmap mVerSliderBM;
|
|
179 private Canvas mVerSliderCv;
|
|
180
|
|
181 private Bitmap[] mHorSlidersBM = new Bitmap[3];
|
|
182 private Canvas[] mHorSlidersCv = new Canvas[3];
|
|
183
|
|
184 private Paint mValDimmer;
|
|
185
|
|
186 //NEW_METHOD_WORK_NEEDED_HERE
|
|
187 //Add Paints to represent the icon for the new method
|
|
188 private Paint mOvalHueSatSmall;
|
|
189
|
|
190 private Paint mPosMarker;
|
|
191 private Paint mText;
|
|
192
|
|
193 private Rect mOldSwatchRect = new Rect();
|
|
194 private Rect mNewSwatchRect = new Rect();
|
|
195 private Rect mPaletteRect = new Rect();
|
|
196 private Rect mVerSliderRect = new Rect();
|
|
197
|
|
198 private int[] mSpectrumColorsRev;
|
|
199 private int mOriginalColor = 0; //The color passed in at the beginning, which can be reverted to at any time by tapping the old swatch.
|
|
200 private float[] mHSV = new float[3];
|
|
201 private int[] mRGB = new int[3];
|
|
202 private float[] mYUV = new float[3];
|
|
203 private String mHexStr = "";
|
|
204 private boolean mHSVenabled = true; //Only true if an HSV method is enabled
|
|
205 private boolean mRGBenabled = true; //Only true if an RGB method is enabled
|
|
206 private boolean mYUVenabled = true; //Only true if a YUV method is enabled
|
|
207 private boolean mHexenabled = true; //Only true if an RGB method is enabled
|
|
208 private int[] mCoord = new int[3]; //For drawing slider/palette markers
|
|
209 private int mFocusedControl = -1; //Which control receives trackball events.
|
|
210 private OnColorChangedListener mListener;
|
|
211
|
|
212 /**
|
|
213 * Ctor.
|
|
214 * @param c
|
|
215 * @param l
|
|
216 * @param width Used to determine orientation and adjust layout accordingly
|
|
217 * @param height Used to determine orientation and adjust layout accordingly
|
|
218 * @param color The initial color
|
|
219 * @throws Exception
|
|
220 */
|
|
221 ColorPickerView(Context c, OnColorChangedListener l, int width, int height, int color)
|
|
222 throws Exception {
|
|
223 super(c);
|
|
224 //We need to make the dialog focusable to retrieve trackball events.
|
|
225 setFocusable(true);
|
|
226 mListener = l;
|
|
227 mOriginalColor = color;
|
|
228 Color.colorToHSV(color, mHSV);
|
|
229 updateAllFromHSV();
|
|
230
|
|
231 //Setup the layout based on whether this is a portrait or landscape orientation.
|
|
232 if (width <= height) { //Portrait layout
|
|
233 SWATCH_WIDTH = (PALETTE_DIM + SLIDER_THICKNESS) / 2;
|
|
234 PALETTE_POS_X = 0;
|
|
235 PALETTE_POS_Y = TEXT_SIZE * 4 + SWATCH_HEIGHT;
|
|
236 //Set more rects, lots of rects
|
|
237 mOldSwatchRect.set(0, TEXT_SIZE * 4, SWATCH_WIDTH, TEXT_SIZE * 4 + SWATCH_HEIGHT);
|
|
238 mNewSwatchRect.set(SWATCH_WIDTH, TEXT_SIZE * 4, SWATCH_WIDTH * 2, TEXT_SIZE * 4 + SWATCH_HEIGHT);
|
|
239 mPaletteRect.set(0, PALETTE_POS_Y, PALETTE_DIM, PALETTE_POS_Y + PALETTE_DIM);
|
|
240 mVerSliderRect.set(PALETTE_DIM, PALETTE_POS_Y, PALETTE_DIM + SLIDER_THICKNESS, PALETTE_POS_Y + PALETTE_DIM);
|
|
241 TEXT_HSV_POS[0] = 3;
|
|
242 TEXT_HSV_POS[1] = 0;
|
|
243 TEXT_RGB_POS[0] = TEXT_HSV_POS[0] + 50;
|
|
244 TEXT_RGB_POS[1] = TEXT_HSV_POS[1];
|
|
245 TEXT_YUV_POS[0] = TEXT_HSV_POS[0] + 100;
|
|
246 TEXT_YUV_POS[1] = TEXT_HSV_POS[1];
|
|
247 TEXT_HEX_POS[0] = TEXT_HSV_POS[0] + 150;
|
|
248 TEXT_HEX_POS[1] = TEXT_HSV_POS[1];
|
|
249 VIEW_DIM_X = PALETTE_DIM + SLIDER_THICKNESS;
|
|
250 VIEW_DIM_Y = SWATCH_HEIGHT + PALETTE_DIM + TEXT_SIZE * 4;
|
|
251 }
|
|
252 else { //Landscape layout
|
|
253 SWATCH_WIDTH = 110;
|
|
254 PALETTE_POS_X = SWATCH_WIDTH;
|
|
255 PALETTE_POS_Y = 0;
|
|
256 //Set more rects, lots of rects
|
|
257 mOldSwatchRect.set(0, TEXT_SIZE * 7, SWATCH_WIDTH, TEXT_SIZE * 7 + SWATCH_HEIGHT);
|
|
258 mNewSwatchRect.set(0, TEXT_SIZE * 7 + SWATCH_HEIGHT, SWATCH_WIDTH, TEXT_SIZE * 7 + SWATCH_HEIGHT * 2);
|
|
259 mPaletteRect.set(SWATCH_WIDTH, PALETTE_POS_Y, SWATCH_WIDTH + PALETTE_DIM, PALETTE_POS_Y + PALETTE_DIM);
|
|
260 mVerSliderRect.set(SWATCH_WIDTH + PALETTE_DIM, PALETTE_POS_Y, SWATCH_WIDTH + PALETTE_DIM + SLIDER_THICKNESS, PALETTE_POS_Y + PALETTE_DIM);
|
|
261 TEXT_HSV_POS[0] = 3;
|
|
262 TEXT_HSV_POS[1] = 0;
|
|
263 TEXT_RGB_POS[0] = TEXT_HSV_POS[0];
|
|
264 TEXT_RGB_POS[1] = (int)(TEXT_HSV_POS[1] + TEXT_SIZE * 3.5);
|
|
265 TEXT_YUV_POS[0] = TEXT_HSV_POS[0] + 50;
|
|
266 TEXT_YUV_POS[1] = (int)(TEXT_HSV_POS[1] + TEXT_SIZE * 3.5);
|
|
267 TEXT_HEX_POS[0] = TEXT_HSV_POS[0] + 50;
|
|
268 TEXT_HEX_POS[1] = TEXT_HSV_POS[1];
|
|
269 VIEW_DIM_X = PALETTE_POS_X + PALETTE_DIM + SLIDER_THICKNESS;
|
|
270 VIEW_DIM_Y = Math.max(mNewSwatchRect.bottom, PALETTE_DIM);
|
|
271 }
|
|
272
|
|
273 //Rainbows make everybody happy!
|
|
274 mSpectrumColorsRev = new int[] {
|
|
275 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF,
|
|
276 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000,
|
|
277 };
|
|
278 //Setup all the Paint and Shader objects. There are lots of them!
|
|
279 //NEW_METHOD_WORK_NEEDED_HERE
|
|
280 //Add Paints to represent the palettes of the new method's UI controllers
|
|
281 mSwatchOld = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
282 mSwatchOld.setStyle(Paint.Style.FILL);
|
|
283 mSwatchOld.setColor(Color.HSVToColor(mHSV));
|
|
284 mSwatchNew = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
285 mSwatchNew.setStyle(Paint.Style.FILL);
|
|
286 mSwatchNew.setColor(Color.HSVToColor(mHSV));
|
|
287 Shader shaderA = new SweepGradient(0, 0, mSpectrumColorsRev, null);
|
|
288 Shader shaderB = new RadialGradient(0, 0, PALETTE_CENTER_X, 0xFFFFFFFF, 0xFF000000, Shader.TileMode.CLAMP);
|
|
289 Shader shader = new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SCREEN);
|
|
290 mOvalHueSat = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
291 mOvalHueSat.setShader(shader);
|
|
292 mOvalHueSat.setStyle(Paint.Style.FILL);
|
|
293 mOvalHueSat.setDither(true);
|
|
294 mVerSliderBM = Bitmap.createBitmap(SLIDER_THICKNESS, PALETTE_DIM, Bitmap.Config.RGB_565);
|
|
295 mVerSliderCv = new Canvas(mVerSliderBM);
|
|
296
|
|
297 for (int i = 0; i < 3; i++) {
|
|
298 mHorSlidersBM[i] = Bitmap.createBitmap(PALETTE_DIM, SLIDER_THICKNESS, Bitmap.Config.RGB_565);
|
|
299 mHorSlidersCv[i] = new Canvas(mHorSlidersBM[i]);
|
|
300 }
|
|
301
|
|
302 mValDimmer = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
303 mValDimmer.setStyle(Paint.Style.FILL);
|
|
304 mValDimmer.setDither(true);
|
|
305 mValDimmer.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
|
|
306 //Whew, we're done making the big Paints and Shaders for the swatches, palettes, and sliders.
|
|
307 //Now we need to make the Paints and Shaders that will draw the little method icons in the method selector list.
|
|
308 //NEW_METHOD_WORK_NEEDED_HERE
|
|
309 //Add Paints to represent the icon for the new method
|
|
310 shaderA = new SweepGradient(0, 0, mSpectrumColorsRev, null);
|
|
311 shaderB = new RadialGradient(0, 0, PALETTE_DIM / 2, 0xFFFFFFFF, 0xFF000000, Shader.TileMode.CLAMP);
|
|
312 shader = new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SCREEN);
|
|
313 mOvalHueSatSmall = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
314 mOvalHueSatSmall.setShader(shader);
|
|
315 mOvalHueSatSmall.setStyle(Paint.Style.FILL);
|
|
316 //Make a simple stroking Paint for drawing markers and borders and stuff like that.
|
|
317 mPosMarker = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
318 mPosMarker.setStyle(Paint.Style.STROKE);
|
|
319 mPosMarker.setStrokeWidth(2);
|
|
320 //Make a basic text Paint.
|
|
321 mText = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
322 mText.setTextSize(TEXT_SIZE);
|
|
323 mText.setColor(Color.WHITE);
|
|
324 //Kickstart
|
|
325 initUI();
|
|
326 }
|
|
327
|
|
328 /**
|
|
329 * Draw the entire view (the entire dialog).
|
|
330 */
|
|
331 @Override
|
|
332 protected void onDraw(Canvas canvas) {
|
|
333 //Draw the old and new swatches
|
|
334 drawSwatches(canvas);
|
|
335 //Write the text
|
|
336 writeColorParams(canvas);
|
|
337
|
|
338 //Draw the palette and sliders (the UI)
|
|
339 if (mMethod == METHOD_HS_V_PALETTE)
|
|
340 drawHSV1Palette(canvas);
|
|
341 }
|
|
342
|
|
343 /**
|
|
344 * Draw the old and new swatches.
|
|
345 * @param canvas
|
|
346 */
|
|
347 private void drawSwatches(Canvas canvas) {
|
|
348 float[] hsv = new float[3];
|
|
349 mText.setTextSize(16);
|
|
350 //Draw the original swatch
|
|
351 canvas.drawRect(mOldSwatchRect, mSwatchOld);
|
|
352 Color.colorToHSV(mOriginalColor, hsv);
|
|
353
|
|
354 //if (UberColorPickerDialog.isGray(mColor)) //Don't need this right here, but imp't to note
|
|
355 // hsv[1] = 0;
|
|
356 if (hsv[2] > .5)
|
|
357 mText.setColor(Color.BLACK);
|
|
358
|
|
359 canvas.drawText("Revert", mOldSwatchRect.left + SWATCH_WIDTH / 2 - mText.measureText("Revert") / 2, mOldSwatchRect.top + 16, mText);
|
|
360 mText.setColor(Color.WHITE);
|
|
361 //Draw the new swatch
|
|
362 canvas.drawRect(mNewSwatchRect, mSwatchNew);
|
|
363
|
|
364 if (mHSV[2] > .5)
|
|
365 mText.setColor(Color.BLACK);
|
|
366
|
|
367 canvas.drawText("Accept", mNewSwatchRect.left + SWATCH_WIDTH / 2 - mText.measureText("Accept") / 2, mNewSwatchRect.top + 16, mText);
|
|
368 mText.setColor(Color.WHITE);
|
|
369 mText.setTextSize(TEXT_SIZE);
|
|
370 }
|
|
371
|
|
372 /**
|
|
373 * Write the color parametes (HSV, RGB, YUV, Hex, etc.).
|
|
374 * @param canvas
|
|
375 */
|
|
376 private void writeColorParams(Canvas canvas) {
|
|
377 if (mHSVenabled) {
|
|
378 canvas.drawText("H: " + Integer.toString((int)(mHSV[0] / 360.0f * 255)), TEXT_HSV_POS[0], TEXT_HSV_POS[1] + TEXT_SIZE, mText);
|
|
379 canvas.drawText("S: " + Integer.toString((int)(mHSV[1] * 255)), TEXT_HSV_POS[0], TEXT_HSV_POS[1] + TEXT_SIZE * 2, mText);
|
|
380 canvas.drawText("V: " + Integer.toString((int)(mHSV[2] * 255)), TEXT_HSV_POS[0], TEXT_HSV_POS[1] + TEXT_SIZE * 3, mText);
|
|
381 }
|
|
382
|
|
383 if (mRGBenabled) {
|
|
384 canvas.drawText("R: " + mRGB[0], TEXT_RGB_POS[0], TEXT_RGB_POS[1] + TEXT_SIZE, mText);
|
|
385 canvas.drawText("G: " + mRGB[1], TEXT_RGB_POS[0], TEXT_RGB_POS[1] + TEXT_SIZE * 2, mText);
|
|
386 canvas.drawText("B: " + mRGB[2], TEXT_RGB_POS[0], TEXT_RGB_POS[1] + TEXT_SIZE * 3, mText);
|
|
387 }
|
|
388
|
|
389 if (mYUVenabled) {
|
|
390 canvas.drawText("Y: " + Integer.toString((int)(mYUV[0] * 255)), TEXT_YUV_POS[0], TEXT_YUV_POS[1] + TEXT_SIZE, mText);
|
|
391 canvas.drawText("U: " + Integer.toString((int)((mYUV[1] + .5f) * 255)), TEXT_YUV_POS[0], TEXT_YUV_POS[1] + TEXT_SIZE * 2, mText);
|
|
392 canvas.drawText("V: " + Integer.toString((int)((mYUV[2] + .5f) * 255)), TEXT_YUV_POS[0], TEXT_YUV_POS[1] + TEXT_SIZE * 3, mText);
|
|
393 }
|
|
394
|
|
395 if (mHexenabled)
|
|
396 canvas.drawText("#" + mHexStr, TEXT_HEX_POS[0], TEXT_HEX_POS[1] + TEXT_SIZE, mText);
|
|
397 }
|
|
398
|
|
399 /**
|
|
400 * Place a small circle on the 2D palette to indicate the current values.
|
|
401 * @param canvas
|
|
402 * @param markerPosX
|
|
403 * @param markerPosY
|
|
404 */
|
|
405 private void mark2DPalette(Canvas canvas, int markerPosX, int markerPosY) {
|
|
406 mPosMarker.setColor(Color.BLACK);
|
|
407 canvas.drawOval(new RectF(markerPosX - 5, markerPosY - 5, markerPosX + 5, markerPosY + 5), mPosMarker);
|
|
408 mPosMarker.setColor(Color.WHITE);
|
|
409 canvas.drawOval(new RectF(markerPosX - 3, markerPosY - 3, markerPosX + 3, markerPosY + 3), mPosMarker);
|
|
410 }
|
|
411
|
|
412 /**
|
|
413 * Draw a line across the slider to indicate its current value.
|
|
414 * @param canvas
|
|
415 * @param markerPos
|
|
416 */
|
|
417 private void markVerSlider(Canvas canvas, int markerPos) {
|
|
418 mPosMarker.setColor(Color.BLACK);
|
|
419 canvas.drawRect(new Rect(0, markerPos - 2, SLIDER_THICKNESS, markerPos + 3), mPosMarker);
|
|
420 mPosMarker.setColor(Color.WHITE);
|
|
421 canvas.drawRect(new Rect(0, markerPos, SLIDER_THICKNESS, markerPos + 1), mPosMarker);
|
|
422 }
|
|
423
|
|
424 /**
|
|
425 * Frame the slider to indicate that it has trackball focus.
|
|
426 * @param canvas
|
|
427 */
|
|
428 private void hilightFocusedVerSlider(Canvas canvas) {
|
|
429 mPosMarker.setColor(Color.WHITE);
|
|
430 canvas.drawRect(new Rect(0, 0, SLIDER_THICKNESS, PALETTE_DIM), mPosMarker);
|
|
431 mPosMarker.setColor(Color.BLACK);
|
|
432 canvas.drawRect(new Rect(2, 2, SLIDER_THICKNESS - 2, PALETTE_DIM - 2), mPosMarker);
|
|
433 }
|
|
434
|
|
435 /**
|
|
436 * Frame the 2D palette to indicate that it has trackball focus.
|
|
437 * @param canvas
|
|
438 */
|
|
439 private void hilightFocusedOvalPalette(Canvas canvas) {
|
|
440 mPosMarker.setColor(Color.WHITE);
|
|
441 canvas.drawOval(new RectF(-PALETTE_RADIUS, -PALETTE_RADIUS, PALETTE_RADIUS, PALETTE_RADIUS), mPosMarker);
|
|
442 mPosMarker.setColor(Color.BLACK);
|
|
443 canvas.drawOval(new RectF(-PALETTE_RADIUS + 2, -PALETTE_RADIUS + 2, PALETTE_RADIUS - 2, PALETTE_RADIUS - 2), mPosMarker);
|
|
444 }
|
|
445
|
|
446 //NEW_METHOD_WORK_NEEDED_HERE
|
|
447 //To add a new method, replicate the basic draw functions here. Use the 2D palette or 1D sliders as templates for the new method.
|
|
448 /**
|
|
449 * Draw the UI for HSV with angular H and radial S combined in 2D and a 1D V slider.
|
|
450 * @param canvas
|
|
451 */
|
|
452 private void drawHSV1Palette(Canvas canvas) {
|
|
453 canvas.save();
|
|
454 canvas.translate(PALETTE_POS_X, PALETTE_POS_Y);
|
|
455 //Draw the 2D palette
|
|
456 canvas.translate(PALETTE_CENTER_X, PALETTE_CENTER_Y);
|
|
457 canvas.drawOval(new RectF(-PALETTE_RADIUS, -PALETTE_RADIUS, PALETTE_RADIUS, PALETTE_RADIUS), mOvalHueSat);
|
|
458 canvas.drawOval(new RectF(-PALETTE_RADIUS, -PALETTE_RADIUS, PALETTE_RADIUS, PALETTE_RADIUS), mValDimmer);
|
|
459
|
|
460 if (mFocusedControl == 0)
|
|
461 hilightFocusedOvalPalette(canvas);
|
|
462
|
|
463 mark2DPalette(canvas, mCoord[0], mCoord[1]);
|
|
464 canvas.translate(-PALETTE_CENTER_X, -PALETTE_CENTER_Y);
|
|
465 //Draw the 1D slider
|
|
466 canvas.translate(PALETTE_DIM, 0);
|
|
467 canvas.drawBitmap(mVerSliderBM, 0, 0, null);
|
|
468
|
|
469 if (mFocusedControl == 1)
|
|
470 hilightFocusedVerSlider(canvas);
|
|
471
|
|
472 markVerSlider(canvas, mCoord[2]);
|
|
473 canvas.restore();
|
|
474 }
|
|
475
|
|
476 /**
|
|
477 * Initialize the current color chooser's UI (set its color parameters and set its palette and slider values accordingly).
|
|
478 */
|
|
479 private void initUI() {
|
|
480 initHSV1Palette();
|
|
481 //Focus on the first controller (arbitrary).
|
|
482 mFocusedControl = 0;
|
|
483 }
|
|
484
|
|
485 //NEW_METHOD_WORK_NEEDED_HERE
|
|
486 //To add a new method, replicate and extend the last init function shown below
|
|
487 /**
|
|
488 * Initialize a color chooser.
|
|
489 */
|
|
490 private void initHSV1Palette() {
|
|
491 setOvalValDimmer();
|
|
492 setVerValSlider();
|
|
493 float angle = 2 * PI - mHSV[0] / (180 / 3.1415927f);
|
|
494 float radius = mHSV[1] * PALETTE_RADIUS;
|
|
495 mCoord[0] = (int)(FloatMath.cos(angle) * radius);
|
|
496 mCoord[1] = (int)(FloatMath.sin(angle) * radius);
|
|
497 mCoord[2] = PALETTE_DIM - (int)(mHSV[2] * PALETTE_DIM);
|
|
498 }
|
|
499
|
|
500 //NEW_METHOD_WORK_NEEDED_HERE
|
|
501 //To add a new method, replicate and extend the set functions below, one per UI controller in the new method
|
|
502 /**
|
|
503 * Adjust a Paint which, when painted, dims its underlying object to show the effects of varying value (brightness).
|
|
504 */
|
|
505 private void setOvalValDimmer() {
|
|
506 float[] hsv = new float[3];
|
|
507 hsv[0] = mHSV[0];
|
|
508 hsv[1] = 0;
|
|
509 hsv[2] = mHSV[2];
|
|
510 int gray = Color.HSVToColor(hsv);
|
|
511 mValDimmer.setColor(gray);
|
|
512 }
|
|
513
|
|
514 /**
|
|
515 * Create a linear gradient shader to show variations in value.
|
|
516 */
|
|
517 private void setVerValSlider() {
|
|
518 float[] hsv = new float[3];
|
|
519 hsv[0] = mHSV[0];
|
|
520 hsv[1] = mHSV[1];
|
|
521 hsv[2] = 1;
|
|
522 int col = Color.HSVToColor(hsv);
|
|
523 int colors[] = new int[2];
|
|
524 colors[0] = col;
|
|
525 colors[1] = 0xFF000000;
|
|
526 GradientDrawable gradDraw = new GradientDrawable(Orientation.TOP_BOTTOM, colors);
|
|
527 gradDraw.setDither(true);
|
|
528 gradDraw.setLevel(10000);
|
|
529 gradDraw.setBounds(0, 0, SLIDER_THICKNESS, PALETTE_DIM);
|
|
530 gradDraw.draw(mVerSliderCv);
|
|
531 }
|
|
532
|
|
533 /**
|
|
534 * Report the correct tightly bounded dimensions of the view.
|
|
535 */
|
|
536 @Override
|
|
537 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
538 setMeasuredDimension(VIEW_DIM_X, VIEW_DIM_Y);
|
|
539 }
|
|
540
|
|
541 /**
|
|
542 * Wrap Math.round(). I'm not a Java expert. Is this the only way to avoid writing "(int)Math.round" everywhere?
|
|
543 * @param x
|
|
544 * @return
|
|
545 */
|
|
546 private int round(double x) {
|
|
547 return (int)Math.round(x);
|
|
548 }
|
|
549
|
|
550 /**
|
|
551 * Limit a value to the range [0,1].
|
|
552 * @param n
|
|
553 * @return
|
|
554 */
|
|
555 private float pinToUnit(float n) {
|
|
556 if (n < 0) {
|
|
557 n = 0;
|
|
558 }
|
|
559 else if (n > 1) {
|
|
560 n = 1;
|
|
561 }
|
|
562
|
|
563 return n;
|
|
564 }
|
|
565
|
|
566 /**
|
|
567 * Limit a value to the range [0,max].
|
|
568 * @param n
|
|
569 * @param max
|
|
570 * @return
|
|
571 */
|
|
572 private float pin(float n, float max) {
|
|
573 if (n < 0) {
|
|
574 n = 0;
|
|
575 }
|
|
576 else if (n > max) {
|
|
577 n = max;
|
|
578 }
|
|
579
|
|
580 return n;
|
|
581 }
|
|
582
|
|
583 /**
|
|
584 * Limit a value to the range [min,max].
|
|
585 * @param n
|
|
586 * @param min
|
|
587 * @param max
|
|
588 * @return
|
|
589 */
|
|
590 private float pin(float n, float min, float max) {
|
|
591 if (n < min) {
|
|
592 n = min;
|
|
593 }
|
|
594 else if (n > max) {
|
|
595 n = max;
|
|
596 }
|
|
597
|
|
598 return n;
|
|
599 }
|
|
600
|
|
601 /**
|
|
602 * No clue what this does (some sort of average/mean I presume). It came with the original UberColorPickerDialog
|
|
603 * in the API Demos and wasn't documented. I don't feel like spending any time figuring it out, I haven't looked at it at all.
|
|
604 * @param s
|
|
605 * @param d
|
|
606 * @param p
|
|
607 * @return
|
|
608 */
|
|
609 private int ave(int s, int d, float p) {
|
|
610 return s + round(p * (d - s));
|
|
611 }
|
|
612
|
|
613 /**
|
|
614 * Came with the original UberColorPickerDialog in the API Demos, wasn't documented. I believe it takes an array of
|
|
615 * colors and a value in the range [0,1] and interpolates a resulting color in a seemingly predictable manner.
|
|
616 * I haven't looked at it at all.
|
|
617 * @param colors
|
|
618 * @param unit
|
|
619 * @return
|
|
620 */
|
|
621 private int interpColor(int colors[], float unit) {
|
|
622 if (unit <= 0) {
|
|
623 return colors[0];
|
|
624 }
|
|
625
|
|
626 if (unit >= 1) {
|
|
627 return colors[colors.length - 1];
|
|
628 }
|
|
629
|
|
630 float p = unit * (colors.length - 1);
|
|
631 int i = (int)p;
|
|
632 p -= i;
|
|
633 // now p is just the fractional part [0...1) and i is the index
|
|
634 int c0 = colors[i];
|
|
635 int c1 = colors[i + 1];
|
|
636 int a = ave(Color.alpha(c0), Color.alpha(c1), p);
|
|
637 int r = ave(Color.red(c0), Color.red(c1), p);
|
|
638 int g = ave(Color.green(c0), Color.green(c1), p);
|
|
639 int b = ave(Color.blue(c0), Color.blue(c1), p);
|
|
640 return Color.argb(a, r, g, b);
|
|
641 }
|
|
642
|
|
643 /**
|
|
644 * A standard point-in-rect routine.
|
|
645 * @param x
|
|
646 * @param y
|
|
647 * @param r
|
|
648 * @return true if point x,y is in rect r
|
|
649 */
|
|
650 public boolean ptInRect(int x, int y, Rect r) {
|
|
651 return x > r.left && x < r.right && y > r.top && y < r.bottom;
|
|
652 }
|
|
653
|
|
654 /**
|
|
655 * Process trackball events. Used mainly for fine-tuned color adjustment, or alternatively to switch between slider controls.
|
|
656 */
|
|
657 @Override
|
|
658 public boolean dispatchTrackballEvent(MotionEvent event) {
|
|
659 float x = event.getX();
|
|
660 float y = event.getY();
|
|
661 //A longer event history implies faster trackball movement.
|
|
662 //Use it to infer a larger jump and therefore faster palette/slider adjustment.
|
|
663 int jump = event.getHistorySize() + 1;
|
|
664
|
|
665 switch (event.getAction()) {
|
|
666 case MotionEvent.ACTION_DOWN: {
|
|
667 }
|
|
668 break;
|
|
669
|
|
670 case MotionEvent.ACTION_MOVE: {
|
|
671 //NEW_METHOD_WORK_NEEDED_HERE
|
|
672 //To add a new method, replicate and extend the appropriate entry in this list,
|
|
673 //depending on whether you use 1D or 2D controllers
|
|
674 switch (mMethod) {
|
|
675 case METHOD_HS_V_PALETTE:
|
|
676 if (mFocusedControl == 0) {
|
|
677 changeHSPalette(x, y, jump);
|
|
678 }
|
|
679 else if (mFocusedControl == 1) {
|
|
680 if (y < 0)
|
|
681 changeSlider(mFocusedControl, true, jump);
|
|
682 else if (y > 0)
|
|
683 changeSlider(mFocusedControl, false, jump);
|
|
684 }
|
|
685
|
|
686 break;
|
|
687 }
|
|
688 }
|
|
689 break;
|
|
690
|
|
691 case MotionEvent.ACTION_UP: {
|
|
692 }
|
|
693 break;
|
|
694 }
|
|
695
|
|
696 return true;
|
|
697 }
|
|
698
|
|
699 //NEW_METHOD_WORK_NEEDED_HERE
|
|
700 //To add a new method, replicate and extend the appropriate functions below,
|
|
701 //one per UI controller in the new method
|
|
702 /**
|
|
703 * Effect a trackball change to a 2D palette.
|
|
704 * @param x -1: negative x change, 0: no x change, +1: positive x change.
|
|
705 * @param y -1: negative y change, 0, no y change, +1: positive y change.
|
|
706 * @param jump the amount by which to change.
|
|
707 */
|
|
708 private void changeHSPalette(float x, float y, int jump) {
|
|
709 int x2 = 0, y2 = 0;
|
|
710
|
|
711 if (x < 0)
|
|
712 x2 = -jump;
|
|
713 else if (x > 0)
|
|
714 x2 = jump;
|
|
715
|
|
716 if (y < 0)
|
|
717 y2 = -jump;
|
|
718 else if (y > 0)
|
|
719 y2 = jump;
|
|
720
|
|
721 mCoord[0] += x2;
|
|
722 mCoord[1] += y2;
|
|
723
|
|
724 if (mCoord[0] < -PALETTE_RADIUS)
|
|
725 mCoord[0] = -PALETTE_RADIUS;
|
|
726 else if (mCoord[0] > PALETTE_RADIUS)
|
|
727 mCoord[0] = PALETTE_RADIUS;
|
|
728
|
|
729 if (mCoord[1] < -PALETTE_RADIUS)
|
|
730 mCoord[1] = -PALETTE_RADIUS;
|
|
731 else if (mCoord[1] > PALETTE_RADIUS)
|
|
732 mCoord[1] = PALETTE_RADIUS;
|
|
733
|
|
734 float radius = FloatMath.sqrt(mCoord[0] * mCoord[0] + mCoord[1] * mCoord[1]);
|
|
735
|
|
736 if (radius > PALETTE_RADIUS)
|
|
737 radius = PALETTE_RADIUS;
|
|
738
|
|
739 float angle = (float)Math.atan2(mCoord[1], mCoord[0]);
|
|
740 // need to turn angle [-PI ... PI] into unit [0....1]
|
|
741 float unit = angle / (2 * PI);
|
|
742
|
|
743 if (unit < 0) {
|
|
744 unit += 1;
|
|
745 }
|
|
746
|
|
747 mCoord[0] = round(FloatMath.cos(angle) * radius);
|
|
748 mCoord[1] = round(FloatMath.sin(angle) * radius);
|
|
749 int c = interpColor(mSpectrumColorsRev, unit);
|
|
750 float[] hsv = new float[3];
|
|
751 Color.colorToHSV(c, hsv);
|
|
752 mHSV[0] = hsv[0];
|
|
753 mHSV[1] = radius / PALETTE_RADIUS;
|
|
754 updateAllFromHSV();
|
|
755 mSwatchNew.setColor(Color.HSVToColor(mHSV));
|
|
756 setVerValSlider();
|
|
757 invalidate();
|
|
758 }
|
|
759
|
|
760 /**
|
|
761 * Effect a trackball change to a 1D slider.
|
|
762 * @param slider id of the slider to be effected
|
|
763 * @param increase true if the change is an increase, false if a decrease
|
|
764 * @param jump the amount by which to change in units of the range [0,255]
|
|
765 */
|
|
766 private void changeSlider(int slider, boolean increase, int jump) {
|
|
767 //NEW_METHOD_WORK_NEEDED_HERE
|
|
768 //It is only necessary to add an entry here for a new method if the new method uses a 1D slider.
|
|
769 //Note, some sliders are horizontal and others are vertical.
|
|
770 //They differ a bit, especially in a sign flip on the vertical axis.
|
|
771 if (mMethod == METHOD_HS_V_PALETTE) {
|
|
772 //slider *must* equal 1
|
|
773 mHSV[2] += (increase ? jump : -jump) / 256.0f;
|
|
774 mHSV[2] = pinToUnit(mHSV[2]);
|
|
775 updateAllFromHSV();
|
|
776 mCoord[2] = PALETTE_DIM - (int)(mHSV[2] * PALETTE_DIM);
|
|
777 mSwatchNew.setColor(Color.HSVToColor(mHSV));
|
|
778 setOvalValDimmer();
|
|
779 invalidate();
|
|
780 }
|
|
781 }
|
|
782
|
|
783 /**
|
|
784 * Keep all colorspace representations in sync.
|
|
785 */
|
|
786 private void updateRGBfromHSV() {
|
|
787 int color = Color.HSVToColor(mHSV);
|
|
788 mRGB[0] = Color.red(color);
|
|
789 mRGB[1] = Color.green(color);
|
|
790 mRGB[2] = Color.blue(color);
|
|
791 }
|
|
792
|
|
793 /**
|
|
794 * Keep all colorspace representations in sync.
|
|
795 */
|
|
796 private void updateYUVfromRGB() {
|
|
797 float r = mRGB[0] / 255.0f;
|
|
798 float g = mRGB[1] / 255.0f;
|
|
799 float b = mRGB[2] / 255.0f;
|
|
800 ColorMatrix cm = new ColorMatrix();
|
|
801 cm.setRGB2YUV();
|
|
802 final float[] a = cm.getArray();
|
|
803 mYUV[0] = a[0] * r + a[1] * g + a[2] * b;
|
|
804 mYUV[0] = pinToUnit(mYUV[0]);
|
|
805 mYUV[1] = a[5] * r + a[6] * g + a[7] * b;
|
|
806 mYUV[1] = pin(mYUV[1], -.5f, .5f);
|
|
807 mYUV[2] = a[10] * r + a[11] * g + a[12] * b;
|
|
808 mYUV[2] = pin(mYUV[2], -.5f, .5f);
|
|
809 }
|
|
810
|
|
811 /**
|
|
812 * Keep all colorspace representations in sync.
|
|
813 */
|
|
814 private void updateHexFromHSV() {
|
|
815 //For now, assume 100% opacity
|
|
816 mHexStr = Integer.toHexString(Color.HSVToColor(mHSV)).toUpperCase();
|
|
817 mHexStr = mHexStr.substring(2, mHexStr.length());
|
|
818 }
|
|
819
|
|
820 /**
|
|
821 * Keep all colorspace representations in sync.
|
|
822 */
|
|
823 private void updateAllFromHSV() {
|
|
824 //Update mRGB
|
|
825 if (mRGBenabled || mYUVenabled)
|
|
826 updateRGBfromHSV();
|
|
827
|
|
828 //Update mYUV
|
|
829 if (mYUVenabled)
|
|
830 updateYUVfromRGB();
|
|
831
|
|
832 //Update mHexStr
|
|
833 if (mRGBenabled)
|
|
834 updateHexFromHSV();
|
|
835 }
|
|
836
|
|
837 /**
|
|
838 * Process touch events: down, move, and up
|
|
839 */
|
|
840 @Override
|
|
841 public boolean onTouchEvent(MotionEvent event) {
|
|
842 float x = event.getX();
|
|
843 float y = event.getY();
|
|
844 //Generate coordinates which are palette=local with the origin at the upper left of the main 2D palette
|
|
845 int y2 = (int)(pin(round(y - PALETTE_POS_Y), PALETTE_DIM));
|
|
846 //Generate coordinates which are palette-local with the origin at the center of the main 2D palette
|
|
847 float circlePinnedX = x - PALETTE_POS_X - PALETTE_CENTER_X;
|
|
848 float circlePinnedY = y - PALETTE_POS_Y - PALETTE_CENTER_Y;
|
|
849 //Is the event in a swatch?
|
|
850 boolean inSwatchOld = ptInRect(round(x), round(y), mOldSwatchRect);
|
|
851 boolean inSwatchNew = ptInRect(round(x), round(y), mNewSwatchRect);
|
|
852 //Get the event's distance from the center of the main 2D palette
|
|
853 float radius = FloatMath.sqrt(circlePinnedX * circlePinnedX + circlePinnedY * circlePinnedY);
|
|
854 //Is the event in a circle-pinned 2D palette?
|
|
855 boolean inOvalPalette = radius <= PALETTE_RADIUS;
|
|
856
|
|
857 //Pin the radius
|
|
858 if (radius > PALETTE_RADIUS)
|
|
859 radius = PALETTE_RADIUS;
|
|
860
|
|
861 //Is the event in a vertical slider to the right of the main 2D palette
|
|
862 boolean inVerSlider = ptInRect(round(x), round(y), mVerSliderRect);
|
|
863
|
|
864 switch (event.getAction()) {
|
|
865 case MotionEvent.ACTION_DOWN:
|
|
866 mTracking = TRACKED_NONE;
|
|
867
|
|
868 if (inSwatchOld)
|
|
869 mTracking = TRACK_SWATCH_OLD;
|
|
870 else if (inSwatchNew)
|
|
871 mTracking = TRACK_SWATCH_NEW;
|
|
872 //NEW_METHOD_WORK_NEEDED_HERE
|
|
873 //To add a new method, replicate and extend the last entry in this list
|
|
874 else if (mMethod == METHOD_HS_V_PALETTE) {
|
|
875 if (inOvalPalette) {
|
|
876 mTracking = TRACK_HS_PALETTE;
|
|
877 mFocusedControl = 0;
|
|
878 }
|
|
879 else if (inVerSlider) {
|
|
880 mTracking = TRACK_VER_VALUE_SLIDER;
|
|
881 mFocusedControl = 1;
|
|
882 }
|
|
883 }
|
|
884
|
|
885 case MotionEvent.ACTION_MOVE:
|
|
886
|
|
887 //NEW_METHOD_WORK_NEEDED_HERE
|
|
888 //To add a new method, replicate and extend the entries in this list,
|
|
889 //one per UI controller the new method requires.
|
|
890 if (mTracking == TRACK_HS_PALETTE) {
|
|
891 float angle = (float)java.lang.Math.atan2(circlePinnedY, circlePinnedX);
|
|
892 // need to turn angle [-PI ... PI] into unit [0....1]
|
|
893 float unit = angle / (2 * PI);
|
|
894
|
|
895 if (unit < 0) {
|
|
896 unit += 1;
|
|
897 }
|
|
898
|
|
899 mCoord[0] = round(FloatMath.cos(angle) * radius);
|
|
900 mCoord[1] = round(FloatMath.sin(angle) * radius);
|
|
901 int c = interpColor(mSpectrumColorsRev, unit);
|
|
902 float[] hsv = new float[3];
|
|
903 Color.colorToHSV(c, hsv);
|
|
904 mHSV[0] = hsv[0];
|
|
905 mHSV[1] = radius / PALETTE_RADIUS;
|
|
906 updateAllFromHSV();
|
|
907 mSwatchNew.setColor(Color.HSVToColor(mHSV));
|
|
908 setVerValSlider();
|
|
909 invalidate();
|
|
910 }
|
|
911 else if (mTracking == TRACK_VER_VALUE_SLIDER) {
|
|
912 if (mCoord[2] != y2) {
|
|
913 mCoord[2] = y2;
|
|
914 float value = 1.0f - (float)y2 / (float)PALETTE_DIM;
|
|
915 mHSV[2] = value;
|
|
916 updateAllFromHSV();
|
|
917 mSwatchNew.setColor(Color.HSVToColor(mHSV));
|
|
918 setOvalValDimmer();
|
|
919 invalidate();
|
|
920 }
|
|
921 }
|
|
922
|
|
923 break;
|
|
924
|
|
925 case MotionEvent.ACTION_UP:
|
|
926
|
|
927 //NEW_METHOD_WORK_NEEDED_HERE
|
|
928 //To add a new method, replicate and extend the last entry in this list.
|
|
929 if (mTracking == TRACK_SWATCH_OLD && inSwatchOld) {
|
|
930 Color.colorToHSV(mOriginalColor, mHSV);
|
|
931 mSwatchNew.setColor(mOriginalColor);
|
|
932 initUI();
|
|
933 invalidate();
|
|
934 }
|
|
935 else if (mTracking == TRACK_SWATCH_NEW && inSwatchNew) {
|
|
936 mListener.colorChanged(mSwatchNew.getColor());
|
|
937 invalidate();
|
|
938 }
|
|
939
|
|
940 mTracking = TRACKED_NONE;
|
|
941 break;
|
|
942 }
|
|
943
|
|
944 return true;
|
|
945 }
|
|
946 }
|
|
947 }
|