package org.openstreetmap.josm.gui.mappaint; import java.awt.Color; import java.util.Collection; import java.util.LinkedList; import javax.swing.ImageIcon; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.tools.ColorHelper; import org.xml.sax.Attributes; import org.xml.sax.helpers.DefaultHandler; public class ElemStyleHandler extends DefaultHandler { boolean inDoc, inRule, inCondition, inLine, inLineMod, inIcon, inArea, inScaleMax, inScaleMin; boolean hadLine, hadLineMod, hadIcon, hadArea; ElemStyles styles; String styleName; RuleElem rule = new RuleElem(); static class RuleElem { Rule rule = new Rule(); Collection<Rule> rules; long scaleMax; long scaleMin; LineElemStyle line = new LineElemStyle(); LineElemStyle linemod = new LineElemStyle(); AreaElemStyle area = new AreaElemStyle(); IconElemStyle icon = new IconElemStyle(); public void init() { rules = null; scaleMax = 1000000000; scaleMin = 0; line.init(); rule.init(); linemod.init(); area.init(); icon.init(); } } public ElemStyleHandler(String name) { styleName = name; inDoc=inRule=inCondition=inLine=inIcon=inArea=false; rule.init(); styles = MapPaintStyles.getStyles(); } Color convertColor(String colString) { int i = colString.indexOf("#"); Color ret; if(i < 0) { ret = Main.pref.getColor("mappaint."+styleName+"."+colString, Color.red); } else if(i == 0) { ret = ColorHelper.html2color(colString); } else { ret = Main.pref.getColor("mappaint."+styleName+"."+colString.substring(0,i), ColorHelper.html2color(colString.substring(i))); } return ret; } @Override public void startDocument() { inDoc = true; } @Override public void endDocument() { inDoc = false; } private void error(String message) { System.out.println(styleName + " (" + rule.rule.key + "=" + rule.rule.value + "): " + message); } private void startElementLine(String qName, Attributes atts, LineElemStyle line) { for (int count=0; count<atts.getLength(); count++) { if(atts.getQName(count).equals("width")) { String val = atts.getValue(count); if(val.startsWith("+")) { line.setWidth(Integer.parseInt(val.substring(1))); line.widthMode = LineElemStyle.WidthMode.OFFSET; } else if(val.startsWith("-")) { line.setWidth(Integer.parseInt(val)); line.widthMode = LineElemStyle.WidthMode.OFFSET; } else if(val.endsWith("%")) { line.setWidth(Integer.parseInt(val.substring(0, val.length()-1))); line.widthMode = LineElemStyle.WidthMode.PERCENT; } else { line.setWidth(Integer.parseInt(val)); } } else if (atts.getQName(count).equals("colour")) { line.color=convertColor(atts.getValue(count)); } else if (atts.getQName(count).equals("realwidth")) { line.realWidth=Integer.parseInt(atts.getValue(count)); } else if (atts.getQName(count).equals("dashed")) { float[] dashed; try { String[] parts = atts.getValue(count).split(","); dashed = new float[parts.length]; for (int i = 0; i < parts.length; i++) { dashed[i] = (Integer.parseInt(parts[i])); } } catch (NumberFormatException nfe) { boolean isDashed = Boolean.parseBoolean(atts.getValue(count)); if(isDashed) { dashed = new float[]{9}; } else { dashed = new float[0]; } } line.setDashed(dashed); } else if (atts.getQName(count).equals("dashedcolour")) { line.dashedColor=convertColor(atts.getValue(count)); } else if(atts.getQName(count).equals("priority")) { line.priority = Integer.parseInt(atts.getValue(count)); } else if(atts.getQName(count).equals("mode")) { line.over = !atts.getValue(count).equals("under"); } else { error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!"); } } } @Override public void startElement(String uri,String name, String qName, Attributes atts) { if (inDoc==true) { if (qName.equals("rule")) { inRule=true; } else if (qName.equals("rules")) { if(styleName == null) { String n = atts.getValue("name"); if(n == null) { n = "standard"; } styleName = n; } } else if (qName.equals("scale_max")) { inScaleMax = true; } else if (qName.equals("scale_min")) { inScaleMin = true; } else if (qName.equals("condition") && inRule) { inCondition=true; Rule r = rule.rule; if(r.key != null) { if(rule.rules == null) { rule.rules = new LinkedList<Rule>(); } rule.rules.add(new Rule(rule.rule)); r = new Rule(); rule.rules.add(r); } for (int count=0; count<atts.getLength(); count++) { if(atts.getQName(count).equals("k")) { r.key = atts.getValue(count); } else if(atts.getQName(count).equals("v")) { r.value = atts.getValue(count); } else if(atts.getQName(count).equals("b")) { r.boolValue = atts.getValue(count); } else { error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!"); } } if(r.key == null) { error("The condition has no key!"); } } else if (qName.equals("line")) { hadLine = inLine = true; startElementLine(qName, atts, rule.line); if(rule.line.widthMode != LineElemStyle.WidthMode.ABSOLUTE) { error("Relative widths are not possible for normal lines"); rule.line.widthMode = LineElemStyle.WidthMode.ABSOLUTE; } } else if (qName.equals("linemod")) { hadLineMod = inLineMod = true; startElementLine(qName, atts, rule.linemod); } else if (qName.equals("icon")) { inIcon = true; for (int count=0; count<atts.getLength(); count++) { if (atts.getQName(count).equals("src")) { ImageIcon icon = MapPaintStyles.getIcon(atts.getValue(count), styleName); hadIcon = (icon != null); rule.icon.icon = icon; } else if (atts.getQName(count).equals("annotate")) { rule.icon.annotate = Boolean.parseBoolean (atts.getValue(count)); } else if(atts.getQName(count).equals("priority")) { rule.icon.priority = Integer.parseInt(atts.getValue(count)); } else { error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!"); } } } else if (qName.equals("area")) { hadArea = inArea = true; for (int count=0; count<atts.getLength(); count++) { if (atts.getQName(count).equals("colour")) { rule.area.color=convertColor(atts.getValue(count)); } else if (atts.getQName(count).equals("closed")) { rule.area.closed=Boolean.parseBoolean(atts.getValue(count)); } else if(atts.getQName(count).equals("priority")) { rule.area.priority = Integer.parseInt(atts.getValue(count)); } else { error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!"); } } } else { error("The element \"" + qName + "\" is unknown!"); } } } @Override public void endElement(String uri,String name, String qName) { if (inRule && qName.equals("rule")) { if(hadLine) { styles.add(styleName, rule.rule, rule.rules, new LineElemStyle(rule.line, rule.scaleMax, rule.scaleMin)); } if(hadLineMod) { styles.addModifier(styleName, rule.rule, rule.rules, new LineElemStyle(rule.linemod, rule.scaleMax, rule.scaleMin)); } if(hadIcon) { styles.add(styleName, rule.rule, rule.rules, new IconElemStyle(rule.icon, rule.scaleMax, rule.scaleMin)); } if(hadArea) { styles.add(styleName, rule.rule, rule.rules, new AreaElemStyle(rule.area, rule.scaleMax, rule.scaleMin)); } inRule = false; hadLine = hadLineMod = hadIcon = hadArea = false; rule.init(); } else if (inCondition && qName.equals("condition")) { inCondition = false; } else if (inLine && qName.equals("line")) { inLine = false; } else if (inLineMod && qName.equals("linemod")) { inLineMod = false; } else if (inIcon && qName.equals("icon")) { inIcon = false; } else if (inArea && qName.equals("area")) { inArea = false; } else if (qName.equals("scale_max")) { inScaleMax = false; } else if (qName.equals("scale_min")) { inScaleMin = false; } } @Override public void characters(char ch[], int start, int length) { if (inScaleMax == true) { rule.scaleMax = Long.parseLong(new String(ch, start, length)); } else if (inScaleMin == true) { rule.scaleMin = Long.parseLong(new String(ch, start, length)); } } }