b1f67289065c7a99d60ad339fb4b4727a6a59c56
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / color / Color.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.utils.ui.color;\r
13 \r
14 import org.eclipse.swt.graphics.Device;\r
15 import org.eclipse.swt.graphics.RGB;\r
16 \r
17 /**\r
18  * Color class that can use both RGB and HSV values.\r
19  * \r
20  * @author Marko Luukkainen\r
21  *\r
22  */\r
23 public class Color implements Comparable<Color>{\r
24 \r
25     private int r;\r
26 \r
27     private int g;\r
28 \r
29     private int b;\r
30 \r
31     private float h;\r
32 \r
33     private float s;\r
34 \r
35     private float v;\r
36 \r
37     public Color() {\r
38         r = 255;\r
39         g = 255;\r
40         b = 255;\r
41         updateHSV();\r
42     }\r
43 \r
44     public Color(int r, int g, int b) {\r
45         this.r = r;\r
46         this.g = g;\r
47         this.b = b;\r
48         updateHSV();\r
49     }\r
50     \r
51     public Color(float h, float s, float v) {\r
52         this.h = h;\r
53         this.s = s;\r
54         this.v = v;\r
55         updateRGB();    \r
56     }\r
57     \r
58     public Color(double h, double s, double v) {\r
59         this.h = (float)h;\r
60         this.s = (float)s;\r
61         this.v = (float)v;\r
62         updateRGB();     \r
63     }\r
64     \r
65     public Color(RGB rgb) {\r
66         this.r = rgb.red;\r
67         this.g = rgb.green;\r
68         this.b = rgb.blue;\r
69         updateHSV();\r
70     }\r
71     \r
72     public Color(Color color) {\r
73         this.r = color.r;\r
74         this.g = color.g;\r
75         this.b = color.b;\r
76         this.h = color.h;\r
77         this.s = color.s;\r
78         this.v = color.v;\r
79     }\r
80     \r
81     /**\r
82      * Sets color form AWT color. Alpha component is omitted.\r
83      * @param color\r
84      */\r
85     public Color(java.awt.Color color) {\r
86         this.r = color.getRed();\r
87         this.g = color.getGreen();\r
88         this.b = color.getBlue();\r
89         updateHSV();\r
90     }\r
91     \r
92     public Color(org.eclipse.swt.graphics.Color color) {\r
93         this.r = color.getRed();\r
94         this.g = color.getGreen();\r
95         this.b = color.getBlue();\r
96         updateHSV();\r
97     }\r
98 \r
99     /**\r
100      * @return Returns the r component of RGB color.\r
101      */\r
102     public int getR() {\r
103         return r;\r
104     }\r
105     \r
106     /**\r
107      * @return Returns the b component of RGB color.\r
108      */\r
109     public int getB() {\r
110         return b;\r
111     }\r
112 \r
113     /**\r
114      * @return Returns the g component of RGB color.\r
115      */\r
116     public int getG() {\r
117         return g;\r
118     }\r
119 \r
120     /**\r
121      * @return Returns the h component of HSV color .\r
122      */\r
123     public float getH() {\r
124         return h;\r
125     }\r
126 \r
127     /**\r
128      * @return Returns the s component of HSV color.\r
129      */\r
130     public float getS() {\r
131         return s;\r
132     }\r
133 \r
134     /**\r
135      * @return Returns the v component of HSV color.\r
136      */\r
137     public float getV() {\r
138         return v;\r
139     }\r
140 \r
141 \r
142     public Color getWhite() {\r
143         return new Color(255, 255, 255);\r
144     }\r
145 \r
146     public Color getBlack() {\r
147         return new Color(0, 0, 0);\r
148     }\r
149 \r
150     public Color getRed() {\r
151         return new Color(255, 0, 0);\r
152     }\r
153 \r
154     public Color getGreen() {\r
155         return new Color(0, 255, 0);\r
156     }\r
157 \r
158     public Color getBlue() {\r
159         return new Color(0, 0, 255);\r
160     }\r
161 \r
162     /**\r
163      * Returns random color\r
164      * @return random color\r
165      */\r
166     public static Color getRandom() {\r
167         return new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255));\r
168     }\r
169     \r
170     /**\r
171      * Returns random color\r
172      * @param minSaturation minimum satuation of random color\r
173      * @param minValue minimum value of random color\r
174      * @return random color with specified mimimum allowed saturation and value\r
175      */\r
176     public static Color getRandomHSV(float minSaturation, float minValue) {\r
177         float randS = (float)Math.random() * (1.f - minSaturation) + minSaturation;\r
178         float randV = (float)Math.random() * (1.f - minValue) + minValue;\r
179         return new Color((float)Math.random() * 360.f, randS, randV);\r
180     }\r
181     \r
182     /**\r
183      * Returns AWT Color\r
184      * @return\r
185      */\r
186     public java.awt.Color getAWTColor() {\r
187         return new java.awt.Color(r,g,b);\r
188     }\r
189     \r
190     /**\r
191      * Returns SWT Color\r
192      * @param device\r
193      * @return\r
194      */\r
195     public org.eclipse.swt.graphics.Color getSWTColor(Device device) {\r
196         return new org.eclipse.swt.graphics.Color(device,r,g,b);\r
197     }\r
198     \r
199     public RGB getRgb() {\r
200         return new RGB(r,g,b);\r
201     }\r
202 \r
203     /**\r
204      * Updates HSV values from RGB values\r
205      * \r
206      */\r
207     private void updateHSV() {\r
208         float tr = (float) r / 255.f;\r
209         float tg = (float) g / 255.f;\r
210         float tb = (float) b / 255.f;\r
211 \r
212         v = Math.max(tr, tg);\r
213         v = Math.max(v, tb);\r
214         float min = Math.min(tr, tg);\r
215         min = Math.min(min, tb);\r
216 \r
217         float delta = v - min;\r
218 \r
219         if (v < 0.01f) {\r
220             s = 0.f;\r
221         } else {\r
222             s = delta / v;\r
223         }\r
224 \r
225         if (s == 0.f) {\r
226             h = Float.NaN; // saturation is 0 -> achromatic color\r
227         } else {\r
228             if (tr == v) {\r
229                 h = 60.f * (tg - tb);\r
230             } else if (tg == v) {\r
231                 h = 120.f + 60.f * (tb - tr);\r
232             } else {\r
233                 h = 240.f + 60.f * (tr - tg);\r
234             }\r
235             if (h < 0.f)\r
236                 h += 360.f;\r
237         }\r
238 \r
239     }\r
240 \r
241     private int floatToInt(float v) {\r
242         return (int) (v * 255.f);\r
243     }\r
244 \r
245     /**\r
246      * Updates RGB values from HSV values\r
247      * \r
248      */\r
249     private void updateRGB() {\r
250         if (s == 0.f) {\r
251             //if (Float.isNaN(h)) {\r
252                 h = Float.NaN;\r
253                 r = floatToInt(v);\r
254                 g = floatToInt(v);\r
255                 b = floatToInt(v);\r
256             //} else {\r
257             //    throw new RuntimeException("Saturation is 0 -> Hue must be undefined");\r
258             //}\r
259         } else {\r
260             while (h < 0.f)\r
261                 h+= 360.f;\r
262             while (h >= 360.f)\r
263                 h-=360.f;\r
264             int hi = (int) Math.floor(h / 60.f);\r
265             float f = h / 60.f - hi;\r
266             float p = v * (1.f - s);\r
267             float q = v * (1.f - (f * s));\r
268             float t = v * (1.f - ((1.f - f) * s));\r
269             switch (hi) {\r
270             case 0:\r
271                 r = floatToInt(v);\r
272                 g = floatToInt(t);\r
273                 b = floatToInt(p);\r
274                 break;\r
275             case 1:\r
276                 r = floatToInt(q);\r
277                 g = floatToInt(v);\r
278                 b = floatToInt(p);\r
279                 break;\r
280             case 2:\r
281                 r = floatToInt(p);\r
282                 g = floatToInt(v);\r
283                 b = floatToInt(t);\r
284                 break;\r
285             case 3:\r
286                 r = floatToInt(p);\r
287                 g = floatToInt(q);\r
288                 b = floatToInt(v);\r
289                 break;\r
290             case 4:\r
291                 r = floatToInt(t);\r
292                 g = floatToInt(p);\r
293                 b = floatToInt(v);\r
294                 break;\r
295             case 5:\r
296                 r = floatToInt(v);\r
297                 g = floatToInt(p);\r
298                 b = floatToInt(q);\r
299                 break;\r
300             }\r
301         }\r
302 \r
303     }\r
304     \r
305     @Override\r
306     public int hashCode() {\r
307         return r ^ (g << 8) ^ (b << 16);\r
308     }\r
309     \r
310     @Override\r
311     public boolean equals(Object obj) {\r
312         if (!(obj instanceof Color))\r
313             return false;\r
314         Color c = (Color) obj;\r
315         return (c.r==r && c.g==g && c.b==b);        \r
316     }\r
317     \r
318     // Uses Hue value for comparisons.\r
319     @Override\r
320     public int compareTo(Color arg0) {\r
321         int d = (int)((h - arg0.h)*10000.f);\r
322         if (d == 0) {\r
323                 d = r - arg0.r;\r
324                 if (d == 0) {\r
325                         d = g - arg0.g;\r
326                         if (d == 0) {\r
327                         d = b - arg0.b;\r
328                 }\r
329                 }\r
330         }\r
331         return d;\r
332         \r
333     }\r
334     \r
335     void setH(float h) {\r
336                 this.h = h;\r
337         }\r
338 \r
339 }\r