1 19 24 25 package org.netbeans.swing.plaf.util; 26 27 import javax.swing.*; 28 import java.awt.*; 29 30 84 public class RelativeColor implements UIDefaults.LazyValue { 85 private Color value = null; 86 private Color fallback = null; 87 99 public RelativeColor(Object base, Object target, Object actual, Object mustContrast) { 100 if (base == null || target == null || actual == null) { 101 throw new NullPointerException ("Null argument(s): " + base + ',' 102 + target + ',' + actual + ',' + mustContrast); 103 } 104 if (base instanceof String ) { 105 baseColorKey = (String ) base; 106 } else { 107 baseColor = (Color) base; 108 } 109 if (target instanceof String ) { 110 targetColorKey = (String ) target; 111 } else { 112 targetColor = (Color) target; 113 } 114 if (actual instanceof String ) { 115 actualColorKey = (String ) actual; 116 } else { 117 actualColor = (Color) actual; 118 } 119 if (mustContrast != null) { 120 if (mustContrast instanceof String ) { 121 mustContrastColorKey = (String ) mustContrast; 122 } else { 123 mustContrastColor = (Color) mustContrast; 124 } 125 } 126 } 127 128 140 public RelativeColor(Color base, Color target, Object actual) { 141 this (base, target, actual, null); 142 } 143 144 public void clear() { 145 value = null; 146 if (actualColorKey != null) { 147 actualColor = null; 148 } 149 if (targetColorKey != null) { 150 targetColor = null; 151 } 152 if (mustContrastColorKey != null) { 153 mustContrastColor = null; 154 } 155 if (baseColorKey != null) { 156 baseColor = null; 157 } 158 } 159 160 public Object createValue(UIDefaults table) { 161 if (value != null) { 162 return value; 163 } 164 Color actual = getActualColor(); 165 Color base = getBaseColor(); 166 if (actual.equals(base)) { 167 value = getTargetColor(); 168 } else { 169 value = deriveColor (base, actual, getTargetColor()); 170 } 171 if (hasMustContrastColor()) { 172 value = ensureContrast(value, getMustContrastColor()); 173 } 174 return value; 175 } 176 177 179 public Color getColor() { 180 return (Color) createValue(null); 181 } 182 183 private Color targetColor = null; 184 private String targetColorKey = null; 185 private Color getTargetColor() { 186 if (checkState (targetColor, targetColorKey)) { 187 targetColor = fetchColor(targetColorKey); 188 } 189 return targetColor; 190 } 191 192 private Color baseColor = null; 193 private String baseColorKey = null; 194 private Color getBaseColor() { 195 if (checkState (baseColor, baseColorKey)) { 196 baseColor = fetchColor(baseColorKey); 197 } 198 return baseColor; 199 } 200 201 private Color mustContrastColor = null; 202 private String mustContrastColorKey = null; 203 private Color getMustContrastColor() { 204 if (checkState (mustContrastColor, mustContrastColorKey)) { 205 mustContrastColor = fetchColor(mustContrastColorKey); 206 } 207 return mustContrastColor; 208 } 209 210 private Color actualColor = null; 211 private String actualColorKey = null; 212 private Color getActualColor() { 213 if (checkState (actualColor, actualColorKey)) { 214 actualColor = fetchColor(actualColorKey); 215 } 216 return actualColor; 217 } 218 219 private boolean hasMustContrastColor() { 220 return mustContrastColor != null || mustContrastColorKey != null; 221 } 222 223 225 private boolean checkState(Color color, String key) { 226 if (color == null && key == null) { 227 throw new NullPointerException ("Both color and key are null for " + 228 this); 229 } 230 return color == null; 231 } 232 233 private Color fetchColor(String key) { 234 Color result = UIManager.getColor(key); 236 if (result == null) { 237 result = fallback; 238 } 239 return result; 240 } 241 242 243 static Color deriveColor (Color base, Color actual, Color target) { 244 float[] baseHSB = Color.RGBtoHSB(base.getRed(), base.getGreen(), 245 base.getBlue(), null); 246 247 float[] targHSB = Color.RGBtoHSB(target.getRed(), target.getGreen(), 248 target.getBlue(), null); 249 250 float[] actualHSB = Color.RGBtoHSB(actual.getRed(), actual.getGreen(), 251 actual.getBlue(), null); 252 253 float[] resultHSB = new float[3]; 254 float[] finalHSB = new float[3]; 255 256 float[] diff = percentageDiff (actualHSB, baseHSB); 257 258 resultHSB[0] = actualHSB[0] + (diff[0] * (targHSB[0] - baseHSB[0])); 259 resultHSB[1] = actualHSB[1] + (diff[1] * (targHSB[1] - baseHSB[1])); 260 resultHSB[2] = actualHSB[2] + (diff[2] * (targHSB[2] - baseHSB[2])); 261 262 finalHSB[0] = saturate (resultHSB[0]); 263 finalHSB[1] = saturate (resultHSB[1]); 264 finalHSB[2] = saturate (resultHSB[2]); 265 266 if (targHSB[1] > 0.1 && resultHSB[1] <= 0.1) { 269 resultHSB[1] = resultHSB[2] * 0.25f; 270 resultHSB[2] = resultHSB[2] - (resultHSB[2] * 0.25f); 271 } 272 273 Color result = new Color (Color.HSBtoRGB(finalHSB[0], finalHSB[1], finalHSB[2])); 274 return result; 275 } 276 277 private static float[] percentageDiff (float[] a, float[] b) { 278 float[] result = new float[3]; 279 for (int i=0; i < 3; i++) { 280 result[i] = 1 - Math.abs(a[i] - b[i]); 281 if (result[i] == 0) { 282 result[i] = 1- a[i]; 283 } 284 } 285 return result; 286 } 287 288 private static final void out (String nm, float[] f) { 289 StringBuffer sb = new StringBuffer (nm); 291 sb.append(": "); 292 for (int i=0; i < f.length; i++) { 293 sb.append (Math.round(f[i] * 100)); 294 if (i != f.length-1) { 295 sb.append(','); 296 sb.append(' '); 297 } 298 } 299 System.err.println(sb.toString()); 300 } 301 302 303 private static float saturate (float f) { 304 return Math.max(0, Math.min(1, f)); 305 } 306 307 308 static Color ensureContrast (Color target, Color contrast) { 309 317 float[] contHSB = Color.RGBtoHSB(contrast.getRed(), contrast.getGreen(), 318 contrast.getBlue(), null); 319 320 float[] targHSB = Color.RGBtoHSB(target.getRed(), target.getGreen(), 321 target.getBlue(), null); 322 323 float[] resultHSB = new float[3]; 324 System.arraycopy(targHSB, 0, resultHSB, 0, 3); 325 326 float satDiff = Math.abs (targHSB[1] - contHSB[1]); 327 float briDiff = Math.abs (targHSB[2] - contHSB[2]); 328 329 if (targHSB[1] > 0.6 && resultHSB[1] > 0.6 || (briDiff < 0.45f && satDiff < 0.4f)) { 330 resultHSB[1] /= 3; 331 satDiff = Math.abs (targHSB[1] - contHSB[1]); 333 } 334 335 if (briDiff < 0.3 || (satDiff < 0.3 && briDiff < 0.5)) { 336 float dir = 1.5f * (0.5f - contHSB[2]); 337 resultHSB[2] = saturate (resultHSB[2] + dir); 338 } 340 341 Color result = new Color (Color.HSBtoRGB(resultHSB[0], resultHSB[1], resultHSB[2])); 342 return result; 343 } 344 } 345 | Popular Tags |