b6bbb301d31d878bd6053645708a8d028ddb362b
[iot-gateway/lighting-gateway.git] / client / AndroidClients / LightingController / src / com / lightingcontroller / ColourPicker.java
1 /**************************************************************************************************
2 Filename: ColourPicker.java
3 Revised: $$
4 Revision: $$
6 Description: ZLL UI
8 Copyright (C) 2007 The Android Open Source Project
10 Licensed under the Apache License, Version 2.0 (the "License");
11 you may not use this file except in compliance with the License.
12 You may obtain a copy of the License at
14 http://www.apache.org/licenses/LICENSE-2.0
16 Unless required by applicable law or agreed to in writing, software
17 distributed under the License is distributed on an "AS IS" BASIS,
18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 See the License for the specific language governing permissions and
20 limitations under the License.
22 Copyright (C) {2012} Texas Instruments Incorporated - http://www.ti.com/
25 Redistribution and use in source and binary forms, with or without
26 modification, are permitted provided that the following conditions
27 are met:
29 Redistributions of source code must retain the above copyright
30 notice, this list of conditions and the following disclaimer.
32 Redistributions in binary form must reproduce the above copyright
33 notice, this list of conditions and the following disclaimer in the
34 documentation and/or other materials provided with the
35 distribution.
37 Neither the name of Texas Instruments Incorporated nor the names of
38 its contributors may be used to endorse or promote products derived
39 from this software without specific prior written permission.
41 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
42 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
43 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
44 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
45 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
51 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 **************************************************************************************************/
55 package com.lightingcontroller;
57 import android.content.Context;
58 import android.graphics.Canvas;
59 import android.graphics.Color;
60 import android.graphics.ComposeShader;
61 import android.graphics.Paint;
62 import android.graphics.PorterDuff;
63 import android.graphics.RadialGradient;
64 import android.graphics.RectF;
65 import android.graphics.Shader;
66 import android.graphics.SweepGradient;
67 import android.util.AttributeSet;
68 import android.util.DisplayMetrics;
69 import android.view.MotionEvent;
70 import android.view.View;
71 import android.view.WindowManager;
73 public class ColourPicker extends View
74 {
75 private static final float PI = 3.1415926f;
77 private int[] mCoord;
78 private float[] mHSV;
80 private zllMain ourContext;
82 private static int CENTER_X;
83 private static int CENTER_Y;
84 private static int HUE_RADIUS;
85 private static int INNER_RADIUS;
86 private static int PALETTE_RADIUS;
88 private static int SAT_RADIUS;
90 public boolean colourKnown = false;
92 int[] mSpectrumColorsRev = new int[] {
93 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF,
94 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000,
95 };
97 Paint mOvalHue;
98 Paint mOvalHueInner;
100 Paint mOvalSat;
101 RectF mRectSat;
102 Paint mArcSat;
103 Paint mPaintSatTextRect;
104 Paint mPaintSatText;
106 Paint mPosMarker;
107 RectF posMarkerRect1;
108 RectF posMarkerRect2;
110 Shader shaderA;
111 Shader shaderB;
112 Shader shaderHue;
114 Shader shaderSat;
117 public ColourPicker(Context context, AttributeSet attr) {
118 super(context, attr);
120 ourContext = (zllMain)context;
122 DisplayMetrics metrics = new DisplayMetrics();
123 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
124 wm.getDefaultDisplay().getMetrics(metrics);
126 double scalefactor;
128 if(metrics.widthPixels < metrics.heightPixels)
129 {
130 scalefactor = 2.5;
131 }
132 else
133 {
134 scalefactor = 5.5;
135 }
137 CENTER_X = (int) ( 1 * (metrics.widthPixels/scalefactor));// (metrics.heightPixels / 2);
138 CENTER_Y = (int) ( 1 * (metrics.widthPixels/scalefactor));// (metrics.heightPixels / 2);
139 HUE_RADIUS = (int) ( 1 * (metrics.widthPixels/scalefactor));//(metrics.heightPixels / 6) - (metrics.heightPixels / 45); //110;
140 INNER_RADIUS = (int) ( 0.63 * (metrics.widthPixels/scalefactor));// (metrics.heightPixels / 10.5); //70;
141 PALETTE_RADIUS = (int) ( 1 * (metrics.widthPixels/scalefactor));//(metrics.heightPixels / 6) - (metrics.heightPixels / 45); //110;;
142 SAT_RADIUS = (int) ( 0.60 * (metrics.widthPixels/scalefactor));//(metrics.heightPixels / 10.5) -5; //65;*/
144 mOvalHue = new Paint(Paint.ANTI_ALIAS_FLAG);
145 mOvalHueInner = new Paint(Paint.ANTI_ALIAS_FLAG);
147 mOvalSat = new Paint(Paint.ANTI_ALIAS_FLAG);
148 mRectSat = new RectF( -SAT_RADIUS, -SAT_RADIUS, SAT_RADIUS, SAT_RADIUS);
149 mArcSat = new Paint();
151 mPosMarker = new Paint(Paint.ANTI_ALIAS_FLAG);
153 shaderA = new SweepGradient(0, 0, mSpectrumColorsRev, null);
154 shaderB = new RadialGradient(CENTER_X, CENTER_Y, HUE_RADIUS, 0xFFFFFFFF, 0xFF000000, Shader.TileMode.CLAMP);
155 shaderHue = new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SCREEN);
157 shaderSat = new RadialGradient(CENTER_X, CENTER_Y, SAT_RADIUS, 0xFF888888, 0xFFFFFFFF, Shader.TileMode.CLAMP);
159 // InitialisePaints Paints
160 mOvalHue.setShader(shaderHue);
161 mOvalHue.setStyle(Paint.Style.FILL);
162 mOvalHue.setDither(true);
164 mOvalSat.setShader(shaderSat);
165 mOvalSat.setStyle(Paint.Style.FILL);
166 mOvalSat.setDither(true);
167 mOvalSat.setColor(0xFFFFFFFF);
169 mArcSat.setAntiAlias(true);
170 mArcSat.setStyle(Paint.Style.FILL);
171 mArcSat.setColor(0xFFFFFFFF);
173 mPosMarker.setStyle(Paint.Style.STROKE);
174 mPosMarker.setStrokeWidth(2);
176 mPaintSatTextRect = new Paint();
177 mPaintSatTextRect.setAntiAlias(true);
178 mPaintSatTextRect.setStyle(Paint.Style.FILL);
179 mPaintSatTextRect.setColor(0XFF000000);
181 mPaintSatText = new Paint();
182 mPaintSatText.setAntiAlias(true);
183 mPaintSatText.setStyle(Paint.Style.FILL);
184 mPaintSatText.setColor(0xFFFFFFFF);
185 mPaintSatText.setTextSize(25);
187 mCoord = new int[2];
188 mHSV = new float[3];
189 mHSV[1] = 1;
191 posMarkerRect1 = new RectF(mCoord[0] - 5, mCoord[1] - 5, mCoord[0] + 5, mCoord[1] + 5);
192 posMarkerRect2 = new RectF(mCoord[0] - 3, mCoord[1] - 3, mCoord[0] + 3, mCoord[1] + 3);
193 }
196 @Override
197 protected void onDraw(Canvas canvas) {
199 canvas.translate(CENTER_X, CENTER_Y);
201 canvas.drawCircle(0, 0, HUE_RADIUS, mOvalHue);
202 canvas.drawCircle(0, 0, INNER_RADIUS, mOvalHueInner);
204 //Sat up
205 canvas.drawArc(mRectSat, (float)182, (float)176, true, mOvalSat);
206 canvas.drawArc(mRectSat, (float)182, (float)176, true, mArcSat);
208 //Sat down
209 canvas.drawArc(mRectSat, (float)2, (float)176, true, mOvalSat);
210 canvas.drawArc(mRectSat, (float)2, (float)176, true, mArcSat);
212 canvas.drawRect(-(SAT_RADIUS-10), 15, (SAT_RADIUS-10), -15, mPaintSatTextRect);
214 mPaintSatText.setColor(0xFFFFFFFF);
215 mPaintSatText.setTextSize(25);
216 String satStr = "Saturation";
217 canvas.drawText(satStr, -60, 8, mPaintSatText);
219 mPaintSatText.setTextSize(35);
220 mPaintSatText.setColor(0xFF000000);
221 satStr = "+";
222 canvas.drawText(satStr, -8, -30, mPaintSatText);
223 satStr = "-";
224 canvas.drawText(satStr, -8, 50, mPaintSatText);
226 if (colourKnown)
227 {
228 posMarkerRect1.set(mCoord[0] - 5, mCoord[1] - 5, mCoord[0] + 5, mCoord[1] + 5);
229 posMarkerRect2.set(mCoord[0] - 3, mCoord[1] - 3, mCoord[0] + 3, mCoord[1] + 3);
231 mPosMarker.setColor(Color.BLACK);
232 canvas.drawOval(posMarkerRect1, mPosMarker);
233 mPosMarker.setColor(Color.WHITE);
234 canvas.drawOval(posMarkerRect2, mPosMarker);
235 }
236 }
238 // Currently Fixed size
239 @Override
240 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
241 setMeasuredDimension(CENTER_X*2, CENTER_Y*2);
242 }
245 public void drawPortraite()
246 {
247 invalidate();
248 }
251 // Weighted average between points
252 private int ave(int s, int d, float p) {
253 return s + java.lang.Math.round(p * (d - s));
254 }
256 // Interpolate colour value between points
257 private int interpColor(int colors[], float unit) {
258 if (unit <= 0) {
259 return colors[0];
260 }
261 if (unit >= 1) {
262 return colors[colors.length - 1];
263 }
265 float p = unit * (colors.length - 1);
266 int i = (int)p;
267 p -= i;
269 // now p is just the fractional part [0...1] and i is the index
270 int c0 = colors[i];
271 int c1 = colors[i+1];
272 int a = ave(Color.alpha(c0), Color.alpha(c1), p);
273 int r = ave(Color.red(c0), Color.red(c1), p);
274 int g = ave(Color.green(c0), Color.green(c1), p);
275 int b = ave(Color.blue(c0), Color.blue(c1), p);
276 System.out.println("the vaient is"+b);
277 return Color.argb(a, r, g, b);
278 }
280 private int round(double x) {
281 return (int)Math.round(x);
282 }
284 public void upDateColorPreivew(byte hue, byte sat)
285 {
286 //update hue preview
287 float unit = (float) hue / 255;
288 if (unit < 0) {
289 unit += 1;
290 }
292 unit = 1 - unit;
294 int c = interpColor(mSpectrumColorsRev, unit );
295 mArcSat.setColor(c);
297 //update sat preview
298 mArcSat.setAlpha(sat);
300 colourKnown = true;
301 }
303 @Override
304 public boolean onTouchEvent(MotionEvent event) {
306 if (!isEnabled())
307 return false;
309 float x = event.getX() - CENTER_X;
310 float y = event.getY() - CENTER_Y;
312 float angle = (float)java.lang.Math.atan2(y, x);
313 // need to turn angle [-PI ... PI] into unit [0....1]
314 float unit = angle/(2*PI);
316 if (unit < 0) {
317 unit += 1;
318 }
320 //Pin the radius
321 float radius = (float)java.lang.Math.sqrt(x * x + y * y);
322 if (radius > PALETTE_RADIUS)
323 radius = PALETTE_RADIUS;
325 if( radius < INNER_RADIUS )
326 {
327 //User adjusted saturation
328 if(angle < 0)
329 {
330 //+ Sat
331 if((mHSV[1]+ 0.10) <= 1)
332 {
333 mHSV[1] += 0.10;
334 }
335 else
336 {
337 mHSV[1] = 1;
338 }
339 }
340 else
341 {
342 //- Sat
343 if((mHSV[1] - 0.10) >= 0)
344 {
345 mHSV[1] -=0.10;
346 }
347 else
348 {
349 mHSV[1] = 0;
350 }
351 }
353 byte hue = (byte) ((mHSV[0]/360)*255);
354 byte sat = (byte) (mHSV[1]*254);
355 ourContext.sendHueSatChange(hue, sat);
356 //update preview
357 mArcSat.setAlpha((byte) (mHSV[1]*254));
358 }
359 else
360 {
361 //User adjusted hue
362 mCoord[0] = round(Math.cos(angle) * (HUE_RADIUS - (HUE_RADIUS-INNER_RADIUS)/2));
363 mCoord[1] = round(Math.sin(angle) * (HUE_RADIUS - (HUE_RADIUS-INNER_RADIUS)/2));
365 int c = interpColor(mSpectrumColorsRev, unit);
366 float[] hsv = new float[3];
367 Color.colorToHSV(c, hsv);
368 mHSV[0] = hsv[0];
370 colourKnown = true;
372 // Update color
373 byte hue = (byte) ((mHSV[0]/360)*255);
374 byte sat = (byte) (mHSV[1]*254);
375 ourContext.sendHueSatChange(hue, sat);
377 //update preview
378 mArcSat.setColor(c);
379 mArcSat.setAlpha((int)(mHSV[1]*255));
380 }
382 invalidate();
384 return true;
385 }
387 }