|
1 /* |
|
2 * CDDL HEADER START |
|
3 * |
|
4 * The contents of this file are subject to the terms of the |
|
5 * Common Development and Distribution License (the "License"). |
|
6 * You may not use this file except in compliance with the License. |
|
7 * |
|
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 * or http://www.opensolaris.org/os/licensing. |
|
10 * See the License for the specific language governing permissions |
|
11 * and limitations under the License. |
|
12 * |
|
13 * When distributing Covered Code, include this CDDL HEADER in each |
|
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 * If applicable, add the following below this CDDL HEADER, with the |
|
16 * fields enclosed by brackets "[]" replaced with your own identifying |
|
17 * information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 * |
|
19 * CDDL HEADER END |
|
20 */ |
|
21 |
|
22 /* |
|
23 * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. |
|
24 */ |
|
25 |
|
26 package com.oracle.solaris.vp.util.swing; |
|
27 |
|
28 import java.awt.*; |
|
29 import javax.swing.*; |
|
30 |
|
31 public class ColorUtil { |
|
32 // |
|
33 // Static data |
|
34 // |
|
35 |
|
36 /** |
|
37 * According to the java.awt.Component API, {@code null} should cause the |
|
38 * background of a {@code Component} to be transparent. But buttons and |
|
39 * other components of some L∓Fs (<cough> metal <cough>) |
|
40 * paint their own background in that case. So a completely transparent |
|
41 * color is provided here instead. |
|
42 */ |
|
43 public static Color TRANSPARENT = new Color(0, 0, 0, 0); |
|
44 |
|
45 // |
|
46 // Static methods |
|
47 // |
|
48 |
|
49 /** |
|
50 * Returns a color identicial to the given color but with a new alpha. |
|
51 * |
|
52 * @param c |
|
53 * the subject color |
|
54 * |
|
55 * @param alpha |
|
56 * the alpha setting |
|
57 */ |
|
58 public static Color alpha(Color c, float alpha) { |
|
59 float[] rgb = c.getRGBColorComponents(null); |
|
60 return new Color(rgb[0], rgb[1], rgb[2], alpha); |
|
61 } |
|
62 |
|
63 /** |
|
64 * Returns a darker version of the given color by the given factor. |
|
65 * <p> |
|
66 * Compared with {@code Color.darker()}, this method provides finer |
|
67 * control over how much to darken the given color. |
|
68 * |
|
69 * @param c |
|
70 * the subject color |
|
71 * |
|
72 * @param factor |
|
73 * a number between 0 (no change) and 1 (resulting color will |
|
74 * be black) inclusive |
|
75 * |
|
76 * @return a darker (closer to black) version of the given color |
|
77 * |
|
78 * @exception IllegalArgumentException |
|
79 * if factor is not betwee 0 and 1 inclusive |
|
80 */ |
|
81 public static Color darker(Color c, float factor) { |
|
82 return blend(c, Color.BLACK, factor); |
|
83 } |
|
84 |
|
85 public static double distance(Color c1, Color c2) { |
|
86 float[] rgb1 = c1.getRGBColorComponents(null); |
|
87 float[] rgb2 = c2.getRGBColorComponents(null); |
|
88 |
|
89 double x = rgb2[0] - rgb1[0]; |
|
90 double y = rgb2[1] - rgb1[1]; |
|
91 double z = rgb2[2] - rgb1[2]; |
|
92 |
|
93 return Math.sqrt(x * x + y * y + z * z); |
|
94 } |
|
95 |
|
96 /** |
|
97 * Blends the given colors by the given factor. |
|
98 * |
|
99 * @param cFrom |
|
100 * the color to blend with cTo |
|
101 * |
|
102 * @param cTo |
|
103 * the color to blend with cFrom |
|
104 * |
|
105 * @param factor |
|
106 * a number between 0 (resulting color will be {@code cFrom}) |
|
107 * and 1 (resulting color will be {@code cTo}) inclusive, with |
|
108 * .5 indicating an even blend between the two |
|
109 * |
|
110 * @return a blend of the given colors |
|
111 * |
|
112 * @exception IllegalArgumentException |
|
113 * if factor is not betwee 0 and 1 inclusive |
|
114 */ |
|
115 public static Color blend(Color cFrom, Color cTo, float factor) { |
|
116 if (factor < 0f || factor > 1f) { |
|
117 throw new IllegalArgumentException( |
|
118 "factor not between 0 and 1: " + factor); |
|
119 } |
|
120 |
|
121 float[] rgbaFrom = cFrom.getRGBComponents(null); |
|
122 float[] rgbaTo = cTo.getRGBComponents(null); |
|
123 |
|
124 rgbaFrom[0] += (rgbaTo[0] - rgbaFrom[0]) * factor; |
|
125 rgbaFrom[1] += (rgbaTo[1] - rgbaFrom[1]) * factor; |
|
126 rgbaFrom[2] += (rgbaTo[2] - rgbaFrom[2]) * factor; |
|
127 |
|
128 return new Color(rgbaFrom[0], rgbaFrom[1], rgbaFrom[2], rgbaFrom[3]); |
|
129 } |
|
130 |
|
131 public static Color getRandomColor() { |
|
132 return new Color( |
|
133 (int)(Math.random() * 256), |
|
134 (int)(Math.random() * 256), |
|
135 (int)(Math.random() * 256)); |
|
136 } |
|
137 |
|
138 /** |
|
139 * Determines whether the given {@code Color} is more dark than light. |
|
140 */ |
|
141 public static boolean isDark(Color c) { |
|
142 double whiteDist = distance(c, Color.WHITE); |
|
143 double blackDist = distance(c, Color.BLACK); |
|
144 |
|
145 return whiteDist > blackDist; |
|
146 } |
|
147 |
|
148 /** |
|
149 * Returns a lighter version of the given color by the given |
|
150 * factor. |
|
151 * <p> |
|
152 * Compared with {@code Color.brighter()}, this method provides finer |
|
153 * control over how much to lighten the given color. |
|
154 * <p> |
|
155 * Note: When {@code factor > 0}, this method differs functionally from |
|
156 * {@code Color.brighter()} - repeated invocations of the former for any |
|
157 * color will eventually yield white, whereas the latter will just create a |
|
158 * brighter version of the same color. For "pure" colors (zero r, g, or b), |
|
159 * repeated invocations of {@code Color.brighter()} will never yield white. |
|
160 * |
|
161 * @param c |
|
162 * the subject color |
|
163 * |
|
164 * @param factor |
|
165 * a number between 0 (no change) and 1 (resulting color will |
|
166 * be white) inclusive |
|
167 * |
|
168 * @return a lighter (closer to white) version of the given color |
|
169 * |
|
170 * @exception IllegalArgumentException |
|
171 * if factor is not betwee 0 and 1 inclusive |
|
172 */ |
|
173 public static Color lighter(Color c, float factor) { |
|
174 return blend(c, Color.WHITE, factor); |
|
175 } |
|
176 |
|
177 public static void main(String args[]) { |
|
178 Color color = Color.RED; |
|
179 JPanel panel = new JPanel(); |
|
180 panel.setLayout(new GridLayout(0, 1, 5, 5)); |
|
181 for (int i = -10; i <= 10; i++) { |
|
182 float factor = (float)i / (float)10; |
|
183 Color lighter = i < 0 ? |
|
184 darker(color, -factor) : lighter(color, factor); |
|
185 JLabel l = new JLabel(factor + ": " + lighter.toString()); |
|
186 l.setBackground(lighter); |
|
187 l.setForeground(isDark(lighter) ? Color.WHITE : Color.BLACK); |
|
188 l.setOpaque(true); |
|
189 panel.add(l); |
|
190 } |
|
191 |
|
192 JFrame frame = new JFrame(); |
|
193 Container c = frame.getContentPane(); |
|
194 c.setLayout(new BorderLayout()); |
|
195 c.add(new JScrollPane(panel), BorderLayout.CENTER); |
|
196 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); |
|
197 frame.pack(); |
|
198 frame.setVisible(true); |
|
199 } |
|
200 } |