/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community 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.osedu.org/licenses/ECL-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.
*/
/**
*
* @author akumar03
*/
package edu.tufts.vue.style;
import java.awt.*;
import java.awt.font.*;
import java.util.*;
public abstract class Style {
public static final String[] DEFAULT_FONT_KEYS = { "font-family","font-size","font-color"};
public static final String[] DEFAULT_FONT_VALUES = {"Arial","12pt","#000000"};
public static final int DEFAULT_FONT_FAMILY_KEY = 0;
public static final int DEFAULT_FONT_SIZE_KEY = 1;
public static final String FONT_COLOR_KEY = "font-color";
public static final String FONT_SIZE_KEY = "font-size";
public static final String FONT_FAMILY_KEY = "font-family";
public static final String FONT_STYLE_KEY = "font-style";
public static final String FONT_WEIGHT_KEY = "font-weight";
public static final int LENGTH_PREFIX = 4;
public static final String OPEN="{";
public static final String CLOSE="}";
public static final String SEMI=";";
public static final String COLON=":";
String name;
private Map<String,String> attributes = new HashMap();
public abstract org.osid.shared.Type getType();
public String getName() {
return name;
}
public void setAttributes(Map<String,String> attributes) {
this.attributes = attributes;
}
public Map<String,String> getAttributes() {
return this.attributes;
}
public String getAttribute(String key) {
return this.attributes.get(key);
}
public void setAttribute(String key,String value) {
if(this.attributes.containsKey(key)){
this.attributes.remove(key);
}
this.attributes.put(key,value);
}
public Font getFont() {
Font f = new Font(DEFAULT_FONT_VALUES[DEFAULT_FONT_FAMILY_KEY],Font.PLAIN,10);
// setting the font color
Map fa = new HashMap();
// Font color is not part of the font it is handled in
/*
if(attributes.get(FONT_COLOR_KEY) != null) {
fa.put(TextAttribute.FOREGROUND,ShorthandParser.parseFontColor(attributes.get(FONT_COLOR_KEY)));
}
*/
if(attributes.get(FONT_SIZE_KEY) != null) {
fa.put(TextAttribute.SIZE,ShorthandParser.parseFontSize(attributes.get(FONT_SIZE_KEY)));
}
if(attributes.get(FONT_FAMILY_KEY) != null) {
fa.put(TextAttribute.FAMILY,attributes.get(FONT_FAMILY_KEY));
}
if(attributes.get(FONT_STYLE_KEY) != null) {
fa.put(TextAttribute.POSTURE,ShorthandParser.parseFontStyle(attributes.get(FONT_STYLE_KEY)));
}
if(attributes.get(FONT_WEIGHT_KEY) != null) {
fa.put(TextAttribute.WEIGHT, ShorthandParser.parseFontWeight(attributes.get(FONT_WEIGHT_KEY)));
}
f = f.deriveFont(fa);
return f;
}
void setDefaultAttributes(){
for(int i = 0;i<DEFAULT_FONT_KEYS.length;i++) {
setAttribute(DEFAULT_FONT_KEYS[i],DEFAULT_FONT_VALUES[i]);
}
}
public String toCSS() {
String s = new String();
s += name+OPEN+"\n";
Set<String> keys= attributes.keySet();
for(String key: keys) {
s += key+":"+attributes.get(key)+";";
}
s +="\n"+CLOSE+"\n";
return s;
}
public static String colorToHex(Color color) {
String colorstr = new String("#");
// Red
String str = Integer.toHexString(color.getRed());
if (str.length() > 2)
str = str.substring(0, 2);
else if (str.length() < 2)
colorstr += "0" + str;
else
colorstr += str;
// Green
str = Integer.toHexString(color.getGreen());
if (str.length() > 2)
str = str.substring(0, 2);
else if (str.length() < 2)
colorstr += "0" + str;
else
colorstr += str;
// Blue
str = Integer.toHexString(color.getBlue());
if (str.length() > 2)
str = str.substring(0, 2);
else if (str.length() < 2)
colorstr += "0" + str;
else
colorstr += str;
return colorstr;
}
/**
* Convert a "#FFFFFF" hex string to a Color.
* If the color specification is bad, an attempt
* will be made to fix it up.
*/
public static final Color hexToColor(String value) {
String digits;
int n = value.length();
value = value.replaceAll(" ","");
if (value.startsWith("#")) {
digits = value.substring(1, Math.min(value.length(), 7));
} else {
digits = value;
}
String hstr = "0x" + digits;
Color c;
try {
c = Color.decode(hstr);
} catch (NumberFormatException nfe) {
c = null;
}
return c;
}
/**
* Convert a color string such as "RED" or "#NNNNNN" or "rgb(r, g, b)"
* to a Color.
*/
public static Color stringToColor(String str) {
Color color = null;
if (str.length() == 0)
color = Color.black;
else if (str.startsWith("rgb(")) {
color = parseRGB(str);
} else if (str.charAt(0) == '#')
color = hexToColor(str);
else if (str.equalsIgnoreCase("Black"))
color = hexToColor("#000000");
else if(str.equalsIgnoreCase("Silver"))
color = hexToColor("#C0C0C0");
else if(str.equalsIgnoreCase("Gray"))
color = hexToColor("#808080");
else if(str.equalsIgnoreCase("White"))
color = hexToColor("#FFFFFF");
else if(str.equalsIgnoreCase("Maroon"))
color = hexToColor("#800000");
else if(str.equalsIgnoreCase("Red"))
color = hexToColor("#FF0000");
else if(str.equalsIgnoreCase("Purple"))
color = hexToColor("#800080");
else if(str.equalsIgnoreCase("Fuchsia"))
color = hexToColor("#FF00FF");
else if(str.equalsIgnoreCase("Green"))
color = hexToColor("#008000");
else if(str.equalsIgnoreCase("Lime"))
color = hexToColor("#00FF00");
else if(str.equalsIgnoreCase("Olive"))
color = hexToColor("#808000");
else if(str.equalsIgnoreCase("Yellow"))
color = hexToColor("#FFFF00");
else if(str.equalsIgnoreCase("Navy"))
color = hexToColor("#000080");
else if(str.equalsIgnoreCase("Blue"))
color = hexToColor("#0000FF");
else if(str.equalsIgnoreCase("Teal"))
color = hexToColor("#008080");
else if(str.equalsIgnoreCase("Aqua"))
color = hexToColor("#00FFFF");
else
color = hexToColor(str); // sometimes get specified without leading #
return color;
}
/**
* Parses a String in the format <code>rgb(r, g, b)</code> where
* each of the Color components is either an integer, or a floating number
* with a % after indicating a percentage value of 255. Values are
* constrained to fit with 0-255. The resulting Color is returned.
*/
private static Color parseRGB(String string) {
// Find the next numeric char
int[] index = new int[1];
index[0] = 4;
int red = getColorComponent(string, index);
int green = getColorComponent(string, index);
int blue = getColorComponent(string, index);
return new Color(red, green, blue);
}
/**
* Returns the next integer value from <code>string</code> starting
* at <code>index[0]</code>. The value can either can an integer, or
* a percentage (floating number ending with %), in which case it is
* multiplied by 255.
*/
private static int getColorComponent(String string, int[] index) {
int length = string.length();
char aChar;
// Skip non-decimal chars
while(index[0] < length && (aChar = string.charAt(index[0])) != '-' &&
!Character.isDigit(aChar) && aChar != '.') {
index[0]++;
}
int start = index[0];
if (start < length && string.charAt(index[0]) == '-') {
index[0]++;
}
while(index[0] < length &&
Character.isDigit(string.charAt(index[0]))) {
index[0]++;
}
if (index[0] < length && string.charAt(index[0]) == '.') {
// Decimal value
index[0]++;
while(index[0] < length &&
Character.isDigit(string.charAt(index[0]))) {
index[0]++;
}
}
if (start != index[0]) {
try {
float value = Float.parseFloat(string.substring
(start, index[0]));
if (index[0] < length && string.charAt(index[0]) == '%') {
index[0]++;
value = value * 255f / 100f;
}
return Math.min(255, Math.max(0, (int)value));
} catch (NumberFormatException nfe) {
// Treat as 0
}
}
return 0;
}
public static final Style getStyle(String reference, Map<String,Style> map) {
Set keys = map.keySet();
Iterator<String> i = keys.iterator();
while(i.hasNext()) {
String key = i.next();
if(key.substring(LENGTH_PREFIX+1).equals(reference)){
return map.get(key);
}
}
return getDefaultStyle();
}
public static final Style getDefaultStyle() {
return NodeStyle.DEFAULT_NODE_STYLE;
}
public String toString() {
return attributes == null ? "null" : attributes.toString();
}
}