OSDN Git Service

dc034eb3871fb9400a60446686d6edad2c0771c1
[android-x86/packages-apps-Eleven.git] / src / com / cyanogenmod / eleven / widgets / ColorPickerView.java
1 /*
2  * Copyright (C) 2010 Daniel Nilsson Copyright (C) 2012 THe CyanogenMod Project
3  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4  * use this file except in compliance with the License. You may obtain a copy of
5  * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
6  * applicable law or agreed to in writing, software distributed under the
7  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
8  * OF ANY KIND, either express or implied. See the License for the specific
9  * language governing permissions and limitations under the License.
10  */
11
12 package com.cyanogenmod.eleven.widgets;
13
14 import android.content.Context;
15 import android.graphics.Canvas;
16 import android.graphics.Color;
17 import android.graphics.ComposeShader;
18 import android.graphics.LinearGradient;
19 import android.graphics.Paint;
20 import android.graphics.Paint.Align;
21 import android.graphics.Paint.Style;
22 import android.graphics.Point;
23 import android.graphics.PorterDuff;
24 import android.graphics.RectF;
25 import android.graphics.Shader;
26 import android.graphics.Shader.TileMode;
27 import android.text.TextUtils;
28 import android.util.AttributeSet;
29 import android.view.MotionEvent;
30 import android.view.View;
31
32 /**
33  * Displays a color picker to the user and allow them to select a color. A
34  * slider for the alpha channel is also available. Enable it by setting
35  * setAlphaSliderVisible(boolean) to true.
36  *
37  * @author Daniel Nilsson
38  */
39 public class ColorPickerView extends View {
40
41     public interface OnColorChangedListener {
42         public void onColorChanged(int color);
43     }
44
45     private final static int PANEL_SAT_VAL = 0;
46
47     private final static int PANEL_HUE = 1;
48
49     private final static int PANEL_ALPHA = 2;
50
51     /**
52      * The width in pixels of the border surrounding all color panels.
53      */
54     private final static float BORDER_WIDTH_PX = 1;
55
56     /**
57      * The width in dp of the hue panel.
58      */
59     private float HUE_PANEL_WIDTH = 30f;
60
61     /**
62      * The height in dp of the alpha panel
63      */
64     private float ALPHA_PANEL_HEIGHT = 20f;
65
66     /**
67      * The distance in dp between the different color panels.
68      */
69     private float PANEL_SPACING = 10f;
70
71     /**
72      * The radius in dp of the color palette tracker circle.
73      */
74     private float PALETTE_CIRCLE_TRACKER_RADIUS = 5f;
75
76     /**
77      * The dp which the tracker of the hue or alpha panel will extend outside of
78      * its bounds.
79      */
80     private float RECTANGLE_TRACKER_OFFSET = 2f;
81
82     private static float mDensity = 1f;
83
84     private OnColorChangedListener mListener;
85
86     private Paint mSatValPaint;
87
88     private Paint mSatValTrackerPaint;
89
90     private Paint mHuePaint;
91
92     private Paint mHueTrackerPaint;
93
94     private Paint mAlphaPaint;
95
96     private Paint mAlphaTextPaint;
97
98     private Paint mBorderPaint;
99
100     private Shader mValShader;
101
102     private Shader mSatShader;
103
104     private Shader mHueShader;
105
106     private Shader mAlphaShader;
107
108     private int mAlpha = 0xff;
109
110     private float mHue = 360f;
111
112     private float mSat = 0f;
113
114     private float mVal = 0f;
115
116     private String mAlphaSliderText = "Alpha";
117
118     private int mSliderTrackerColor = 0xff1c1c1c;
119
120     private int mBorderColor = 0xff6E6E6E;
121
122     private boolean mShowAlphaPanel = false;
123
124     /*
125      * To remember which panel that has the "focus" when processing hardware
126      * button data.
127      */
128     private int mLastTouchedPanel = PANEL_SAT_VAL;
129
130     /**
131      * Offset from the edge we must have or else the finger tracker will get
132      * clipped when it is drawn outside of the view.
133      */
134     private float mDrawingOffset;
135
136     /*
137      * Distance form the edges of the view of where we are allowed to draw.
138      */
139     private RectF mDrawingRect;
140
141     private RectF mSatValRect;
142
143     private RectF mHueRect;
144
145     private RectF mAlphaRect;
146
147     private AlphaPatternDrawable mAlphaPattern;
148
149     private Point mStartTouchPoint = null;
150
151     public ColorPickerView(final Context context) {
152         this(context, null);
153     }
154
155     public ColorPickerView(final Context context, final AttributeSet attrs) {
156         this(context, attrs, 0);
157     }
158
159     public ColorPickerView(final Context context, final AttributeSet attrs, final int defStyle) {
160         super(context, attrs, defStyle);
161         init();
162     }
163
164     private void init() {
165         mDensity = getContext().getResources().getDisplayMetrics().density;
166         PALETTE_CIRCLE_TRACKER_RADIUS *= mDensity;
167         RECTANGLE_TRACKER_OFFSET *= mDensity;
168         HUE_PANEL_WIDTH *= mDensity;
169         ALPHA_PANEL_HEIGHT *= mDensity;
170         PANEL_SPACING = PANEL_SPACING * mDensity;
171
172         mDrawingOffset = calculateRequiredOffset();
173
174         initPaintTools();
175
176         // Needed for receiving track ball motion events.
177         setFocusable(true);
178         setFocusableInTouchMode(true);
179     }
180
181     private void initPaintTools() {
182
183         mSatValPaint = new Paint();
184         mSatValTrackerPaint = new Paint();
185         mHuePaint = new Paint();
186         mHueTrackerPaint = new Paint();
187         mAlphaPaint = new Paint();
188         mAlphaTextPaint = new Paint();
189         mBorderPaint = new Paint();
190
191         mSatValTrackerPaint.setStyle(Style.STROKE);
192         mSatValTrackerPaint.setStrokeWidth(2f * mDensity);
193         mSatValTrackerPaint.setAntiAlias(true);
194
195         mHueTrackerPaint.setColor(mSliderTrackerColor);
196         mHueTrackerPaint.setStyle(Style.STROKE);
197         mHueTrackerPaint.setStrokeWidth(2f * mDensity);
198         mHueTrackerPaint.setAntiAlias(true);
199
200         mAlphaTextPaint.setColor(0xff1c1c1c);
201         mAlphaTextPaint.setTextSize(14f * mDensity);
202         mAlphaTextPaint.setAntiAlias(true);
203         mAlphaTextPaint.setTextAlign(Align.CENTER);
204         mAlphaTextPaint.setFakeBoldText(true);
205
206     }
207
208     private float calculateRequiredOffset() {
209         float offset = Math.max(PALETTE_CIRCLE_TRACKER_RADIUS, RECTANGLE_TRACKER_OFFSET);
210         offset = Math.max(offset, BORDER_WIDTH_PX * mDensity);
211
212         return offset * 1.5f;
213     }
214
215     private int[] buildHueColorArray() {
216
217         final int[] hue = new int[361];
218
219         int count = 0;
220         for (int i = hue.length - 1; i >= 0; i--, count++) {
221             hue[count] = Color.HSVToColor(new float[] {
222                     i, 1f, 1f
223             });
224         }
225
226         return hue;
227     }
228
229     @Override
230     protected void onDraw(final Canvas canvas) {
231
232         if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0) {
233             return;
234         }
235
236         drawSatValPanel(canvas);
237         drawHuePanel(canvas);
238         drawAlphaPanel(canvas);
239
240     }
241
242     private void drawSatValPanel(final Canvas canvas) {
243
244         final RectF rect = mSatValRect;
245
246         if (BORDER_WIDTH_PX > 0) {
247             mBorderPaint.setColor(mBorderColor);
248             canvas.drawRect(mDrawingRect.left, mDrawingRect.top, rect.right + BORDER_WIDTH_PX,
249                     rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
250         }
251
252         if (mValShader == null) {
253             mValShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
254                     0xffffffff, 0xff000000, TileMode.CLAMP);
255         }
256
257         final int rgb = Color.HSVToColor(new float[] {
258                 mHue, 1f, 1f
259         });
260
261         mSatShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top, 0xffffffff, rgb,
262                 TileMode.CLAMP);
263         final ComposeShader mShader = new ComposeShader(mValShader, mSatShader,
264                 PorterDuff.Mode.MULTIPLY);
265         mSatValPaint.setShader(mShader);
266
267         canvas.drawRect(rect, mSatValPaint);
268
269         final Point p = satValToPoint(mSat, mVal);
270
271         mSatValTrackerPaint.setColor(0xff000000);
272         canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS - 1f * mDensity,
273                 mSatValTrackerPaint);
274
275         mSatValTrackerPaint.setColor(0xffdddddd);
276         canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS, mSatValTrackerPaint);
277
278     }
279
280     private void drawHuePanel(final Canvas canvas) {
281
282         final RectF rect = mHueRect;
283
284         if (BORDER_WIDTH_PX > 0) {
285             mBorderPaint.setColor(mBorderColor);
286             canvas.drawRect(rect.left - BORDER_WIDTH_PX, rect.top - BORDER_WIDTH_PX, rect.right
287                     + BORDER_WIDTH_PX, rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
288         }
289
290         if (mHueShader == null) {
291             mHueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
292                     buildHueColorArray(), null, TileMode.CLAMP);
293             mHuePaint.setShader(mHueShader);
294         }
295
296         canvas.drawRect(rect, mHuePaint);
297
298         final float rectHeight = 4 * mDensity / 2;
299
300         final Point p = hueToPoint(mHue);
301
302         final RectF r = new RectF();
303         r.left = rect.left - RECTANGLE_TRACKER_OFFSET;
304         r.right = rect.right + RECTANGLE_TRACKER_OFFSET;
305         r.top = p.y - rectHeight;
306         r.bottom = p.y + rectHeight;
307
308         canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
309
310     }
311
312     private void drawAlphaPanel(final Canvas canvas) {
313
314         if (!mShowAlphaPanel || mAlphaRect == null || mAlphaPattern == null) {
315             return;
316         }
317
318         final RectF rect = mAlphaRect;
319
320         if (BORDER_WIDTH_PX > 0) {
321             mBorderPaint.setColor(mBorderColor);
322             canvas.drawRect(rect.left - BORDER_WIDTH_PX, rect.top - BORDER_WIDTH_PX, rect.right
323                     + BORDER_WIDTH_PX, rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
324         }
325
326         mAlphaPattern.draw(canvas);
327
328         final float[] hsv = new float[] {
329                 mHue, mSat, mVal
330         };
331         final int color = Color.HSVToColor(hsv);
332         final int acolor = Color.HSVToColor(0, hsv);
333
334         mAlphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top, color, acolor,
335                 TileMode.CLAMP);
336
337         mAlphaPaint.setShader(mAlphaShader);
338
339         canvas.drawRect(rect, mAlphaPaint);
340
341         if (!TextUtils.isEmpty(mAlphaSliderText)) {
342             canvas.drawText(mAlphaSliderText, rect.centerX(), rect.centerY() + 4 * mDensity,
343                     mAlphaTextPaint);
344         }
345
346         final float rectWidth = 4 * mDensity / 2;
347
348         final Point p = alphaToPoint(mAlpha);
349
350         final RectF r = new RectF();
351         r.left = p.x - rectWidth;
352         r.right = p.x + rectWidth;
353         r.top = rect.top - RECTANGLE_TRACKER_OFFSET;
354         r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;
355
356         canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
357
358     }
359
360     private Point hueToPoint(final float hue) {
361
362         final RectF rect = mHueRect;
363         final float height = rect.height();
364
365         final Point p = new Point();
366
367         p.y = (int)(height - hue * height / 360f + rect.top);
368         p.x = (int)rect.left;
369
370         return p;
371     }
372
373     private Point satValToPoint(final float sat, final float val) {
374
375         final RectF rect = mSatValRect;
376         final float height = rect.height();
377         final float width = rect.width();
378
379         final Point p = new Point();
380
381         p.x = (int)(sat * width + rect.left);
382         p.y = (int)((1f - val) * height + rect.top);
383
384         return p;
385     }
386
387     private Point alphaToPoint(final int alpha) {
388
389         final RectF rect = mAlphaRect;
390         final float width = rect.width();
391
392         final Point p = new Point();
393
394         p.x = (int)(width - alpha * width / 0xff + rect.left);
395         p.y = (int)rect.top;
396
397         return p;
398
399     }
400
401     private float[] pointToSatVal(float x, float y) {
402
403         final RectF rect = mSatValRect;
404         final float[] result = new float[2];
405
406         final float width = rect.width();
407         final float height = rect.height();
408
409         if (x < rect.left) {
410             x = 0f;
411         } else if (x > rect.right) {
412             x = width;
413         } else {
414             x = x - rect.left;
415         }
416
417         if (y < rect.top) {
418             y = 0f;
419         } else if (y > rect.bottom) {
420             y = height;
421         } else {
422             y = y - rect.top;
423         }
424
425         result[0] = 1.f / width * x;
426         result[1] = 1.f - 1.f / height * y;
427
428         return result;
429     }
430
431     private float pointToHue(float y) {
432
433         final RectF rect = mHueRect;
434
435         final float height = rect.height();
436
437         if (y < rect.top) {
438             y = 0f;
439         } else if (y > rect.bottom) {
440             y = height;
441         } else {
442             y = y - rect.top;
443         }
444
445         return 360f - y * 360f / height;
446     }
447
448     private int pointToAlpha(int x) {
449
450         final RectF rect = mAlphaRect;
451         final int width = (int)rect.width();
452
453         if (x < rect.left) {
454             x = 0;
455         } else if (x > rect.right) {
456             x = width;
457         } else {
458             x = x - (int)rect.left;
459         }
460
461         return 0xff - x * 0xff / width;
462
463     }
464
465     @Override
466     public boolean onTrackballEvent(final MotionEvent event) {
467
468         final float x = event.getX();
469         final float y = event.getY();
470
471         boolean update = false;
472
473         if (event.getAction() == MotionEvent.ACTION_MOVE) {
474
475             switch (mLastTouchedPanel) {
476
477                 case PANEL_SAT_VAL:
478
479                     float sat,
480                     val;
481
482                     sat = mSat + x / 50f;
483                     val = mVal - y / 50f;
484
485                     if (sat < 0f) {
486                         sat = 0f;
487                     } else if (sat > 1f) {
488                         sat = 1f;
489                     }
490
491                     if (val < 0f) {
492                         val = 0f;
493                     } else if (val > 1f) {
494                         val = 1f;
495                     }
496
497                     mSat = sat;
498                     mVal = val;
499
500                     update = true;
501
502                     break;
503
504                 case PANEL_HUE:
505
506                     float hue = mHue - y * 10f;
507
508                     if (hue < 0f) {
509                         hue = 0f;
510                     } else if (hue > 360f) {
511                         hue = 360f;
512                     }
513
514                     mHue = hue;
515
516                     update = true;
517
518                     break;
519
520                 case PANEL_ALPHA:
521
522                     if (!mShowAlphaPanel || mAlphaRect == null) {
523                         update = false;
524                     } else {
525
526                         int alpha = (int)(mAlpha - x * 10);
527
528                         if (alpha < 0) {
529                             alpha = 0;
530                         } else if (alpha > 0xff) {
531                             alpha = 0xff;
532                         }
533
534                         mAlpha = alpha;
535
536                         update = true;
537                     }
538
539                     break;
540             }
541
542         }
543
544         if (update) {
545
546             if (mListener != null) {
547                 mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] {
548                         mHue, mSat, mVal
549                 }));
550             }
551
552             invalidate();
553             return true;
554         }
555
556         return super.onTrackballEvent(event);
557     }
558
559     @Override
560     public boolean onTouchEvent(final MotionEvent event) {
561
562         boolean update = false;
563
564         switch (event.getAction()) {
565
566             case MotionEvent.ACTION_DOWN:
567
568                 mStartTouchPoint = new Point((int)event.getX(), (int)event.getY());
569
570                 update = moveTrackersIfNeeded(event);
571
572                 break;
573
574             case MotionEvent.ACTION_MOVE:
575
576                 update = moveTrackersIfNeeded(event);
577
578                 break;
579
580             case MotionEvent.ACTION_UP:
581
582                 mStartTouchPoint = null;
583
584                 update = moveTrackersIfNeeded(event);
585
586                 break;
587
588         }
589
590         if (update) {
591
592             if (mListener != null) {
593                 mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] {
594                         mHue, mSat, mVal
595                 }));
596             }
597
598             invalidate();
599             return true;
600         }
601
602         return super.onTouchEvent(event);
603     }
604
605     private boolean moveTrackersIfNeeded(final MotionEvent event) {
606
607         if (mStartTouchPoint == null) {
608             return false;
609         }
610
611         boolean update = false;
612
613         final int startX = mStartTouchPoint.x;
614         final int startY = mStartTouchPoint.y;
615
616         if (mHueRect.contains(startX, startY)) {
617             mLastTouchedPanel = PANEL_HUE;
618
619             mHue = pointToHue(event.getY());
620
621             update = true;
622         } else if (mSatValRect.contains(startX, startY)) {
623
624             mLastTouchedPanel = PANEL_SAT_VAL;
625
626             final float[] result = pointToSatVal(event.getX(), event.getY());
627
628             mSat = result[0];
629             mVal = result[1];
630
631             update = true;
632         } else if (mAlphaRect != null && mAlphaRect.contains(startX, startY)) {
633
634             mLastTouchedPanel = PANEL_ALPHA;
635
636             mAlpha = pointToAlpha((int)event.getX());
637
638             update = true;
639         }
640
641         return update;
642     }
643
644     @Override
645     protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
646
647         int width = 0;
648         int height = 0;
649
650         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
651         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
652
653         int widthAllowed = MeasureSpec.getSize(widthMeasureSpec);
654         int heightAllowed = MeasureSpec.getSize(heightMeasureSpec);
655
656         widthAllowed = chooseWidth(widthMode, widthAllowed);
657         heightAllowed = chooseHeight(heightMode, heightAllowed);
658
659         if (!mShowAlphaPanel) {
660             height = (int)(widthAllowed - PANEL_SPACING - HUE_PANEL_WIDTH);
661
662             // If calculated height (based on the width) is more than the
663             // allowed height.
664             if (height > heightAllowed) {
665                 height = heightAllowed;
666                 width = (int)(height + PANEL_SPACING + HUE_PANEL_WIDTH);
667             } else {
668                 width = widthAllowed;
669             }
670         } else {
671
672             width = (int)(heightAllowed - ALPHA_PANEL_HEIGHT + HUE_PANEL_WIDTH);
673
674             if (width > widthAllowed) {
675                 width = widthAllowed;
676                 height = (int)(widthAllowed - HUE_PANEL_WIDTH + ALPHA_PANEL_HEIGHT);
677             } else {
678                 height = heightAllowed;
679             }
680
681         }
682
683         setMeasuredDimension(width, height);
684     }
685
686     private int chooseWidth(final int mode, final int size) {
687         if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
688             return size;
689         } else { // (mode == MeasureSpec.UNSPECIFIED)
690             return getPrefferedWidth();
691         }
692     }
693
694     private int chooseHeight(final int mode, final int size) {
695         if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
696             return size;
697         } else { // (mode == MeasureSpec.UNSPECIFIED)
698             return getPrefferedHeight();
699         }
700     }
701
702     private int getPrefferedWidth() {
703
704         int width = getPrefferedHeight();
705
706         if (mShowAlphaPanel) {
707             width -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
708         }
709
710         return (int)(width + HUE_PANEL_WIDTH + PANEL_SPACING);
711
712     }
713
714     private int getPrefferedHeight() {
715
716         int height = (int)(200 * mDensity);
717
718         if (mShowAlphaPanel) {
719             height += PANEL_SPACING + ALPHA_PANEL_HEIGHT;
720         }
721
722         return height;
723     }
724
725     @Override
726     protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
727         super.onSizeChanged(w, h, oldw, oldh);
728
729         mDrawingRect = new RectF();
730         mDrawingRect.left = mDrawingOffset + getPaddingLeft();
731         mDrawingRect.right = w - mDrawingOffset - getPaddingRight();
732         mDrawingRect.top = mDrawingOffset + getPaddingTop();
733         mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
734
735         setUpSatValRect();
736         setUpHueRect();
737         setUpAlphaRect();
738     }
739
740     private void setUpSatValRect() {
741
742         final RectF dRect = mDrawingRect;
743         float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
744
745         if (mShowAlphaPanel) {
746             panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
747         }
748
749         final float left = dRect.left + BORDER_WIDTH_PX;
750         final float top = dRect.top + BORDER_WIDTH_PX;
751         final float bottom = top + panelSide;
752         final float right = left + panelSide;
753
754         mSatValRect = new RectF(left, top, right, bottom);
755     }
756
757     private void setUpHueRect() {
758         final RectF dRect = mDrawingRect;
759
760         final float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
761         final float top = dRect.top + BORDER_WIDTH_PX;
762         final float bottom = dRect.bottom - BORDER_WIDTH_PX
763                 - (mShowAlphaPanel ? PANEL_SPACING + ALPHA_PANEL_HEIGHT : 0);
764         final float right = dRect.right - BORDER_WIDTH_PX;
765
766         mHueRect = new RectF(left, top, right, bottom);
767     }
768
769     private void setUpAlphaRect() {
770
771         if (!mShowAlphaPanel) {
772             return;
773         }
774
775         final RectF dRect = mDrawingRect;
776
777         final float left = dRect.left + BORDER_WIDTH_PX;
778         final float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
779         final float bottom = dRect.bottom - BORDER_WIDTH_PX;
780         final float right = dRect.right - BORDER_WIDTH_PX;
781
782         mAlphaRect = new RectF(left, top, right, bottom);
783
784         mAlphaPattern = new AlphaPatternDrawable((int)(5 * mDensity));
785         mAlphaPattern.setBounds(Math.round(mAlphaRect.left), Math.round(mAlphaRect.top),
786                 Math.round(mAlphaRect.right), Math.round(mAlphaRect.bottom));
787
788     }
789
790     /**
791      * Set a OnColorChangedListener to get notified when the color selected by
792      * the user has changed.
793      *
794      * @param listener
795      */
796     public void setOnColorChangedListener(final OnColorChangedListener listener) {
797         mListener = listener;
798     }
799
800     /**
801      * Set the color of the border surrounding all panels.
802      *
803      * @param color
804      */
805     public void setBorderColor(final int color) {
806         mBorderColor = color;
807         invalidate();
808     }
809
810     /**
811      * Get the color of the border surrounding all panels.
812      */
813     public int getBorderColor() {
814         return mBorderColor;
815     }
816
817     /**
818      * Get the current color this view is showing.
819      *
820      * @return the current color.
821      */
822     public int getColor() {
823         return Color.HSVToColor(mAlpha, new float[] {
824                 mHue, mSat, mVal
825         });
826     }
827
828     /**
829      * Set the color the view should show.
830      *
831      * @param color The color that should be selected.
832      */
833     public void setColor(final int color) {
834         setColor(color, false);
835     }
836
837     /**
838      * Set the color this view should show.
839      *
840      * @param color The color that should be selected.
841      * @param callback If you want to get a callback to your
842      *            OnColorChangedListener.
843      */
844     public void setColor(final int color, final boolean callback) {
845
846         final int alpha = Color.alpha(color);
847         final int red = Color.red(color);
848         final int blue = Color.blue(color);
849         final int green = Color.green(color);
850
851         final float[] hsv = new float[3];
852
853         Color.RGBToHSV(red, green, blue, hsv);
854
855         mAlpha = alpha;
856         mHue = hsv[0];
857         mSat = hsv[1];
858         mVal = hsv[2];
859
860         if (callback && mListener != null) {
861             mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] {
862                     mHue, mSat, mVal
863             }));
864         }
865
866         invalidate();
867     }
868
869     /**
870      * Get the drawing offset of the color picker view. The drawing offset is
871      * the distance from the side of a panel to the side of the view minus the
872      * padding. Useful if you want to have your own panel below showing the
873      * currently selected color and want to align it perfectly.
874      *
875      * @return The offset in pixels.
876      */
877     public float getDrawingOffset() {
878         return mDrawingOffset;
879     }
880
881     /**
882      * Set if the user is allowed to adjust the alpha panel. Default is false.
883      * If it is set to false no alpha will be set.
884      *
885      * @param visible
886      */
887     public void setAlphaSliderVisible(final boolean visible) {
888
889         if (mShowAlphaPanel != visible) {
890             mShowAlphaPanel = visible;
891
892             /*
893              * Reset all shader to force a recreation. Otherwise they will not
894              * look right after the size of the view has changed.
895              */
896             mValShader = null;
897             mSatShader = null;
898             mHueShader = null;
899             mAlphaShader = null;
900
901             requestLayout();
902         }
903
904     }
905
906     public void setSliderTrackerColor(final int color) {
907         mSliderTrackerColor = color;
908
909         mHueTrackerPaint.setColor(mSliderTrackerColor);
910
911         invalidate();
912     }
913
914     public int getSliderTrackerColor() {
915         return mSliderTrackerColor;
916     }
917
918     /**
919      * Set the text that should be shown in the alpha slider. Set to null to
920      * disable text.
921      *
922      * @param res string resource id.
923      */
924     public void setAlphaSliderText(final int res) {
925         final String text = getContext().getString(res);
926         setAlphaSliderText(text);
927     }
928
929     /**
930      * Set the text that should be shown in the alpha slider. Set to null to
931      * disable text.
932      *
933      * @param text Text that should be shown.
934      */
935     public void setAlphaSliderText(final String text) {
936         mAlphaSliderText = text;
937         invalidate();
938     }
939
940     /**
941      * Get the current value of the text that will be shown in the alpha slider.
942      *
943      * @return
944      */
945     public String getAlphaSliderText() {
946         return mAlphaSliderText;
947     }
948 }