/*
* DefaultEUGStyleSet.java
*
* Created on June 26, 2007, 5:21 PM
*/
package eug.syntax;
import eug.parser.TokenType;
import java.awt.Color;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
/**
*
* @author Michael Myers
*/
public class DefaultEUGStyleSet implements StyleSet {
private static final long serialVersionUID = 1L;
private static final Style DEFAULT_STYLE =
StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
private final Map<Pattern, MutableAttributeSet> keywords =
new HashMap<Pattern, MutableAttributeSet>();
private final Map<TokenType, MutableAttributeSet> tokenStyles =
new EnumMap<TokenType, MutableAttributeSet>(TokenType.class);
private final List<TokenType> overrides = Arrays.asList(new TokenType[] {
TokenType.ULSTRING,
});
/**
* Creates a new instance of DefaultEUGStyleSet
*/
public DefaultEUGStyleSet() {
// addDefaults();
}
/**
* Adds the default keywords. Included are:
* <ul>
* <li>EU3-style dates, such as 1492.1.1</li>
* <li>The constant strings "yes" and "no" (without quotes)</li>
* <li>Country tags (three characters beginning with a capital letter and
* including only numbers and capital letters)</li>
* <li>Numbers</li>
* <li>Comments</li>
* <li>Quote-delimited strings</li>
* </ul>
* Each of these has its own style; for example, "yes" and "no" are in a
* dark blue bold font.
*/
public void addDefaults() {
final StyleContext defaultStyleContext = StyleContext.getDefaultStyleContext();
final Style basic = defaultStyleContext.getStyle(StyleContext.DEFAULT_STYLE);
MutableAttributeSet as;
// Keywords
// Dates (1492.1.1)
as = new SimpleAttributeSet(basic);
StyleConstants.setForeground(as, Color.MAGENTA);
StyleConstants.setBold(as, false);
keywords.put(Pattern.compile("\\d{1,4}\\.\\d{1,2}\\.\\d{1,2}"), as);
// Yes/no
as = new SimpleAttributeSet(basic);
StyleConstants.setForeground(as, Color.BLUE.darker());
StyleConstants.setBold(as, true);
keywords.put(Pattern.compile("(yes|no)", Pattern.CASE_INSENSITIVE), as);
// Country tags
// Lowercase not allowed
as = new SimpleAttributeSet(basic);
StyleConstants.setForeground(as, Color.ORANGE.darker());
StyleConstants.setBold(as, false);
keywords.put(Pattern.compile("[A-Z][A-Z0-9]{2}"), as);
// Numbers
as = new SimpleAttributeSet(basic);
StyleConstants.setForeground(as, Color.GREEN.darker());
StyleConstants.setBold(as, false);
keywords.put(Pattern.compile("[+-]?([0-9]+(\\.[0-9]*)?)"), as);
// Tokens
as = new SimpleAttributeSet(basic);
StyleConstants.setForeground(as, Color.GRAY);
tokenStyles.put(TokenType.COMMENT, as);
as = new SimpleAttributeSet(basic);
StyleConstants.setForeground(as, Color.MAGENTA);
tokenStyles.put(TokenType.DLSTRING, as);
as = new SimpleAttributeSet(basic);
StyleConstants.setForeground(as, Color.BLACK);
StyleConstants.setBold(as, /*true*/ false);
tokenStyles.put(TokenType.IDENT, as);
}
public MutableAttributeSet getStyle(TokenType token, String str) {
if (overrides.contains(token)) {
return getKeywordStyle(str);
} else {
return getTokenStyle(token);
}
}
private MutableAttributeSet getKeywordStyle(String str) {
for (Map.Entry<Pattern, MutableAttributeSet> entry : keywords.entrySet()) {
if (entry.getKey().matcher(str).matches())
return entry.getValue();
}
return DEFAULT_STYLE;
}
private MutableAttributeSet getTokenStyle(TokenType token) {
MutableAttributeSet mas = tokenStyles.get(token);
if (mas == null)
return DEFAULT_STYLE;
return mas;
}
/**
* Adds a custom keyword style to the style set.
* @param pattern the pattern (in java.util.regex.Pattern syntax) that
* describes the keyword or set of keywords.
* @param attrs the <code>AttributeSet</code> that will be used when the
* given pattern is found in the document's text.
* @see #addKeywordStyle(Pattern, MutableAttributeSet)
* @see #removeKeywordStyle(String)
* @see #removeKeywordStyle(Pattern)
*/
public void addKeywordStyle(String pattern, MutableAttributeSet attrs) {
addKeywordStyle(Pattern.compile(pattern), attrs);
}
/**
* Add a custom keyword style to the style set.
* @param pattern the pattern that describes the keyword or set of keywords.
* @param attrs the <code>AttributeSet</code> that will be used when the
* given pattern is found in the document's text.
* @see #addKeywordStyle(String, MutableAttributeSet)
* @see #removeKeywordStyle(Pattern)
* @see #removeKeywordStyle(String)
*/
public void addKeywordStyle(Pattern pattern, MutableAttributeSet attrs) {
keywords.put(pattern, attrs);
}
/**
* Removes the given pattern from the list of keyword patterns.
* @param pattern the pattern (in java.util.regex.Pattern syntax) that
* describes the keyword or set of keywords.
* @see #removeKeywordStyle(Pattern)
* @see #addKeywordStyle(String, MutableAttributeSet)
* @see #addKeywordStyle(Pattern, MutableAttributeSet)
*/
public void removeKeywordStyle(String pattern) {
removeKeywordStyle(Pattern.compile(pattern));
}
/**
* Removes the given pattern from the list of keyword patterns.
* @param pattern the pattern that describes the keyword or set of keywords.
* @see #removeKeywordStyle(String)
* @see #addKeywordStyle(Pattern, MutableAttributeSet)
* @see #addKeywordStyle(String, MutableAttributeSet)
*/
public void removeKeywordStyle(Pattern pattern) {
keywords.remove(pattern);
}
/**
* Adds a custom token style to the style set. If there is already a style
* listed for the given token type, the given attributes will be added to it
* instead of replacing it.
* @param type the TokenType to apply the attributes to.
* @param attrs the <code>AttributeSet</code> that will be used when the
* given pattern is found in the document's text.
* @see #addTokenStyle(TokenType, MutableAttributeSet, boolean)
* @see #addKeywordStyle(String, MutableAttributeSet)
* @see #addKeywordStyle(Pattern, MutableAttributeSet)
*/
public void addTokenStyle(TokenType type, MutableAttributeSet attrs) {
addTokenStyle(type, attrs, false);
}
/**
* Adds a custom token style to the style set. If there is already a style
* listed for the given token type, the parameter <code>override</code>
* determines whether it will be replaced or added to.
* @param type the TokenType to apply the attributes to.
* @param attrs the <code>AttributeSet</code> that will be used when the
* given pattern is found in the document's text.
* @param override whether or not to override any previous attributes for
* the given token type. Ignored if there is no previous entry.
* @see #addTokenStyle(TokenType, MutableAttributeSet)
* @see #addKeywordStyle(String, MutableAttributeSet)
* @see #addKeywordStyle(Pattern, MutableAttributeSet)
*/
public void addTokenStyle(TokenType type, MutableAttributeSet attrs, boolean override) {
if (override) {
// Don't check for a previous listing.
tokenStyles.put(type, attrs);
return;
}
MutableAttributeSet previous = tokenStyles.get(type);
if (previous == null) {
tokenStyles.put(type, attrs);
return;
}
previous.addAttributes(attrs);
}
}