/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package griffon.javafx.formatters;
import griffon.core.resources.formatters.AbstractFormatter;
import griffon.core.resources.formatters.ParseException;
import javafx.scene.paint.Color;
import java.lang.reflect.Field;
import java.util.Arrays;
import static griffon.util.GriffonNameUtils.isBlank;
import static java.lang.Integer.toHexString;
import static org.codehaus.groovy.runtime.StringGroovyMethods.padLeft;
/**
* @author Andres Almiray
* @since 1.3.0
*/
public class ColorFormatter extends AbstractFormatter<Color> {
public static final String PATTERN_SHORT = "#RGB";
public static final String PATTERN_SHORT_WITH_ALPHA = "#RGBA";
public static final String PATTERN_LONG = "#RRGGBB";
public static final String PATTERN_LONG_WITH_ALPHA = "#RRGGBBAA";
public static final String DEFAULT_PATTERN = PATTERN_LONG;
private static final String[] PATTERNS = new String[]{
PATTERN_LONG,
PATTERN_LONG_WITH_ALPHA,
PATTERN_SHORT,
PATTERN_SHORT_WITH_ALPHA
};
public static final ColorFormatter SHORT = new ColorFormatter(PATTERN_SHORT);
public static final ColorFormatter SHORT_WITH_ALPHA = new ColorFormatter(PATTERN_SHORT_WITH_ALPHA);
public static final ColorFormatter LONG = new ColorFormatter(PATTERN_LONG);
public static final ColorFormatter LONG_WITH_ALPHA = new ColorFormatter(PATTERN_LONG_WITH_ALPHA);
public static ColorFormatter getInstance(String pattern) {
return new ColorFormatter(pattern);
}
private final ColorFormatterDelegate delegate;
public ColorFormatter() {
this(DEFAULT_PATTERN);
}
protected ColorFormatter(String pattern) {
if (PATTERN_SHORT.equals(pattern)) {
delegate = new ShortColorFormatterDelegate();
} else if (PATTERN_SHORT_WITH_ALPHA.equals(pattern)) {
delegate = new ShortWithAlphaColorFormatterDelegate();
} else if (PATTERN_LONG.equals(pattern)) {
delegate = new LongColorFormatterDelegate();
} else if (PATTERN_LONG_WITH_ALPHA.equals(pattern)) {
delegate = new LongWithAlphaColorFormatterDelegate();
} else if (isBlank(pattern)) {
delegate = new LongColorFormatterDelegate();
} else {
throw new IllegalArgumentException("Invalid pattern '" + pattern + "'. Valid patterns are " + Arrays.toString(PATTERNS));
}
}
public String format(Color color) {
return delegate.format(color);
}
public Color parse(String str) throws ParseException {
return delegate.parse(str);
}
public static Color parseColor(String str) throws ParseException {
if (str.startsWith("#")) {
switch (str.length()) {
case 4:
return (Color) SHORT.parse(str);
case 5:
return (Color) SHORT_WITH_ALPHA.parse(str);
case 7:
return (Color) LONG.parse(str);
case 9:
return (Color) LONG_WITH_ALPHA.parse(str);
default:
throw parseError(str, Color.class);
}
} else {
// assume it's a Color constant
try {
String colorFieldName = str.toUpperCase();
Field field = Color.class.getField(colorFieldName);
return (Color) field.get(null);
} catch (Exception e) {
throw parseError(str, Color.class, e);
}
}
}
private static interface ColorFormatterDelegate {
String getPattern();
String format(Color color);
Color parse(String str) throws ParseException;
}
private static abstract class AbstractColorFormatterDelegate implements ColorFormatterDelegate {
private final String pattern;
private AbstractColorFormatterDelegate(String pattern) {
this.pattern = pattern;
}
public String getPattern() {
return pattern;
}
}
private static int red(Color color) {
return toIntColor(color.getRed());
}
private static int green(Color color) {
return toIntColor(color.getGreen());
}
private static int blue(Color color) {
return toIntColor(color.getBlue());
}
private static int alpha(Color color) {
return toIntColor(color.getOpacity());
}
private static int toIntColor(double c) {
return new Double(c * 255).intValue();
}
private static class ShortColorFormatterDelegate extends AbstractColorFormatterDelegate {
private ShortColorFormatterDelegate() {
super(PATTERN_SHORT);
}
public String format(Color color) {
if (color == null) {
throw new IllegalArgumentException("Cannot format given Color because it's null");
}
return new StringBuilder("#")
.append(toHexString(red(color)).charAt(0))
.append(toHexString(green(color)).charAt(0))
.append(toHexString(blue(color)).charAt(0))
.toString();
}
public Color parse(String str) throws ParseException {
if (isBlank(str) || !str.startsWith("#") || str.length() != 4) {
throw parseError(str, Color.class);
}
int r = parseHexInt(new StringBuilder()
.append(str.charAt(1))
.append(str.charAt(1))
.toString().toUpperCase(), Color.class);
int g = parseHexInt(new StringBuilder()
.append(str.charAt(2))
.append(str.charAt(2))
.toString().toUpperCase(), Color.class);
int b = parseHexInt(new StringBuilder()
.append(str.charAt(3))
.append(str.charAt(3))
.toString().toUpperCase(), Color.class);
return Color.rgb(r, g, b);
}
}
private static class ShortWithAlphaColorFormatterDelegate extends AbstractColorFormatterDelegate {
private ShortWithAlphaColorFormatterDelegate() {
super(PATTERN_SHORT_WITH_ALPHA);
}
public String format(Color color) {
if (color == null) {
throw new IllegalArgumentException("Cannot format given Color because it's null");
}
return new StringBuilder("#")
.append(toHexString(red(color)).charAt(0))
.append(toHexString(green(color)).charAt(0))
.append(toHexString(blue(color)).charAt(0))
.append(toHexString(alpha(color)).charAt(0))
.toString();
}
public Color parse(String str) throws ParseException {
if (isBlank(str)) return null;
if (!str.startsWith("#") || str.length() != 5) {
throw parseError(str, Color.class);
}
int r = parseHexInt(new StringBuilder()
.append(str.charAt(1))
.append(str.charAt(1))
.toString().toUpperCase(), Color.class);
int g = parseHexInt(new StringBuilder()
.append(str.charAt(2))
.append(str.charAt(2))
.toString().toUpperCase(), Color.class);
int b = parseHexInt(new StringBuilder()
.append(str.charAt(3))
.append(str.charAt(3))
.toString().toUpperCase(), Color.class);
int a = parseHexInt(new StringBuilder()
.append(str.charAt(4))
.append(str.charAt(4))
.toString().toUpperCase(), Color.class);
return Color.rgb(r, g, b, a / 255d);
}
}
private static class LongColorFormatterDelegate extends AbstractColorFormatterDelegate {
private LongColorFormatterDelegate() {
super(PATTERN_LONG);
}
public String format(Color color) {
if (color == null) {
throw new IllegalArgumentException("Cannot format given Color because it's null");
}
return new StringBuilder("#")
.append(padLeft(toHexString(red(color)), 2, "0"))
.append(padLeft(toHexString(green(color)), 2, "0"))
.append(padLeft(toHexString(blue(color)), 2, "0"))
.toString();
}
public Color parse(String str) throws ParseException {
if (isBlank(str)) return null;
if (!str.startsWith("#") || str.length() != 7) {
throw parseError(str, Color.class);
}
int r = parseHexInt(new StringBuilder()
.append(str.charAt(1))
.append(str.charAt(2))
.toString().toUpperCase(), Color.class);
int g = parseHexInt(new StringBuilder()
.append(str.charAt(3))
.append(str.charAt(4))
.toString().toUpperCase(), Color.class);
int b = parseHexInt(new StringBuilder()
.append(str.charAt(5))
.append(str.charAt(6))
.toString().toUpperCase(), Color.class);
return Color.rgb(r, g, b);
}
}
private static class LongWithAlphaColorFormatterDelegate extends AbstractColorFormatterDelegate {
private LongWithAlphaColorFormatterDelegate() {
super(PATTERN_LONG_WITH_ALPHA);
}
public String format(Color color) {
if (color == null) {
throw new IllegalArgumentException("Cannot format given Color because it's null");
}
return new StringBuilder("#")
.append(padLeft(toHexString(red(color)), 2, "0"))
.append(padLeft(toHexString(green(color)), 2, "0"))
.append(padLeft(toHexString(blue(color)), 2, "0"))
.append(padLeft(toHexString(alpha(color)), 2, "0"))
.toString();
}
public Color parse(String str) throws ParseException {
if (isBlank(str)) return null;
if (!str.startsWith("#") || str.length() != 9) {
throw parseError(str, Color.class);
}
int r = parseHexInt(new StringBuilder()
.append(str.charAt(1))
.append(str.charAt(2))
.toString().toUpperCase(), Color.class);
int g = parseHexInt(new StringBuilder()
.append(str.charAt(3))
.append(str.charAt(4))
.toString().toUpperCase(), Color.class);
int b = parseHexInt(new StringBuilder()
.append(str.charAt(5))
.append(str.charAt(6))
.toString().toUpperCase(), Color.class);
int a = parseHexInt(new StringBuilder()
.append(str.charAt(7))
.append(str.charAt(8))
.toString().toUpperCase(), Color.class);
return Color.rgb(r, g, b, a / 255d);
}
}
}