/*
* @(#)FontFormatter.java
*
* Copyright (c) 2009-2010 The authors and contributors of JHotDraw.
*
* You may not use, copy or modify this file, except in compliance with the
* accompanying license terms.
*/
package org.jhotdraw.text;
import javax.annotation.Nullable;
import java.awt.Font;
import java.text.ParseException;
import java.util.HashMap;
import javax.swing.JFormattedTextField.AbstractFormatterFactory;
import javax.swing.text.DefaultFormatter;
import javax.swing.text.DefaultFormatterFactory;
/**
* {@code FontFormatter} is used to format fonts into a textual representation
* which can be edited in an entry field.
* <p>
*
* @author Werner Randelshofer
* @version $Id$
*/
public class FontFormatter extends DefaultFormatter {
private static final long serialVersionUID = 1L;
/**
* Specifies whether the formatter allows null values.
*/
private boolean allowsNullValue = false;
/**
* Specifies whether the formatter allows unknown fonts.
*/
private boolean allowsUnknownFont = false;
/**
* Map of generic font families.
* By default, holds a map of HTML generic font families.
* <a href="http://www.w3.org/TR/CSS2/fonts.html#generic-font-families">
* http://www.w3.org/TR/CSS2/fonts.html#generic-font-families</a>.
*/
@Nullable private HashMap<String, Font> genericFontFamilies = new HashMap<>();
public FontFormatter() {
this(true);
}
public FontFormatter(boolean allowsNullValue) {
this.allowsNullValue = allowsNullValue;
setOverwriteMode(false);
// Map of HTML generic font families.
// @see http://www.w3.org/TR/CSS2/fonts.html#generic-font-families
putGenericFontFamily("serif", new Font("Serif", Font.PLAIN, 12));
putGenericFontFamily("sans-serif", new Font("SansSerif", Font.PLAIN, 12));
putGenericFontFamily("cursive", new Font("SansSerif", Font.ITALIC, 12));
putGenericFontFamily("fantasy", new Font("Serif", Font.PLAIN, 12));
putGenericFontFamily("monospace", new Font("Monospaced", Font.PLAIN, 12));
}
/**
* Sets whether a null value is allowed.
* @param newValue
*/
public void setAllowsNullValue(boolean newValue) {
allowsNullValue = newValue;
}
/**
* Returns true, if null value is allowed.
*/
public boolean getAllowsNullValue() {
return allowsNullValue;
}
/**
* Sets whether unknown font names are allowed.
* @param newValue
*/
public void setAllowsUnknownFont(boolean newValue) {
allowsUnknownFont = newValue;
}
/**
* Returns true, if unknown font names are allowed.
*/
public boolean getAllowsUnknownFont() {
return allowsUnknownFont;
}
/** Clears the generic font families map. */
public void clearGenericFontFamilies() {
genericFontFamilies = null;
}
/** Adds a generic font family. */
public void putGenericFontFamily(String familyName, Font font) {
genericFontFamilies.put(familyName.toLowerCase(), font);
}
@Override
public Object stringToValue(String str) throws ParseException {
// Handle null and empty case
if (str == null || str.trim().length() == 0) {
if (allowsNullValue) {
return null;
} else {
throw new ParseException("Null value is not allowed.", 0);
}
}
String strLC = str.trim().toLowerCase();
Font f = null;
f = genericFontFamilies.get(strLC);
if (f == null) {
f = Font.decode(str);
if (f == null) {
throw new ParseException(str, 0);
}
if (!allowsUnknownFont) {
String fontName = f.getFontName().toLowerCase();
String family = f.getFamily().toLowerCase();
if (!fontName.equals(strLC) &&
!family.equals(strLC) &&
!fontName.equals(strLC + "-derived")) {
throw new ParseException(str, 0);
}
}
}
return f;
}
@Override
public String valueToString(Object value) throws ParseException {
String str = null;
if (value == null) {
if (allowsNullValue) {
str = "";
} else {
throw new ParseException("Null value is not allowed.", 0);
}
} else {
if (!(value instanceof Font)) {
throw new ParseException("Value is not a font " + value, 0);
}
Font f = (Font) value;
str = f.getFontName();
}
return str;
}
/**
* Convenience method for creating a formatter factory with a
* {@code FontFormatter}.
* Uses the RGB_INTEGER format and disallows null values.
*/
public static AbstractFormatterFactory createFormatterFactory() {
return createFormatterFactory(false);
}
/**
* Convenience method for creating a formatter factory with a
* 8@code FontFormatter}.
*/
public static AbstractFormatterFactory createFormatterFactory(boolean allowsNullValue) {
return new DefaultFormatterFactory(new FontFormatter(allowsNullValue));
}
}