package org.openstreetmap.josm.gui.mappaint; import java.awt.Color; import java.util.Collection; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.Way; import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings; import org.openstreetmap.josm.data.osm.visitor.paint.MapPainter; import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors; import org.openstreetmap.josm.tools.I18n; public class LineElemStyle extends ElemStyle implements Comparable<LineElemStyle> { public static final LineElemStyle UNTAGGED_WAY; static { UNTAGGED_WAY = new LineElemStyle(); UNTAGGED_WAY.color = PaintColors.UNTAGGED.get(); } private int width; public int realWidth; //the real width of this line in meter public Color color; private float[] dashed; public Color dashedColor; public boolean over; public enum WidthMode { ABSOLUTE, PERCENT, OFFSET } public WidthMode widthMode; public Collection<LineElemStyle> overlays; public LineElemStyle(LineElemStyle s, long maxScale, long minScale) { this.width = s.width; this.realWidth = s.realWidth; this.color = s.color; this.dashed = s.dashed; this.dashedColor = s.dashedColor; this.over = s.over; this.widthMode = s.widthMode; this.priority = s.priority; this.maxScale = maxScale; this.minScale = minScale; this.rules = s.rules; } public LineElemStyle(LineElemStyle s, Collection<LineElemStyle> overlays) { this.width = s.width; this.realWidth = s.realWidth; this.color = s.color; this.dashed = s.dashed; this.dashedColor = s.dashedColor; this.over = s.over; this.widthMode = s.widthMode; this.priority = s.priority; this.maxScale = s.maxScale; this.minScale = s.minScale; this.rules = s.rules; this.overlays = overlays; this.code = s.code; for (LineElemStyle o : overlays) { this.code += o.code; } } public LineElemStyle() { init(); } public void init() { width = -1; realWidth = 0; dashed = new float[0]; dashedColor = null; priority = 0; color = null; over = true; // only used for line modifications widthMode = WidthMode.ABSOLUTE; overlays = null; } // get width for overlays public int getWidth(int ref) { int res; if(widthMode == WidthMode.ABSOLUTE) { res = width; } else if(widthMode == WidthMode.OFFSET) { res = ref + width; } else { if(width < 0) { res = 0; } else { res = ref*width/100; } } return res <= 0 ? 1 : res; } public int compareTo(LineElemStyle s) { if(s.priority != priority) return s.priority > priority ? 1 : -1; if(!over && s.over) return -1; // we have no idea how to order other objects :-) return 0; } public float[] getDashed() { return dashed; } public void setDashed(float[] dashed) { if (dashed.length == 0) { this.dashed = dashed; return; } boolean found = false; for (int i=0; i<dashed.length; i++) { if (dashed[i] > 0) { found = true; } if (dashed[i] < 0) { System.out.println(I18n.tr("Illegal dash pattern, values must be positive")); } } if (found) { this.dashed = dashed; } else { System.out.println(I18n.tr("Illegal dash pattern, at least one value must be > 0")); } } @Override public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected) { Way w = (Way)primitive; /* show direction arrows, if draw.segment.relevant_directions_only is not set, the way is tagged with a direction key (even if the tag is negated as in oneway=false) or the way is selected */ boolean showDirection = selected || ((!paintSettings.isUseRealWidth()) && (paintSettings.isShowDirectionArrow() && (!paintSettings.isShowRelevantDirectionsOnly() || w.hasDirectionKeys()))); boolean reversedDirection = w.reversedDirection(); /* head only takes over control if the option is true, the direction should be shown at all and not only because it's selected */ boolean showOnlyHeadArrowOnly = showDirection && !selected && paintSettings.isShowHeadArrowOnly(); Node lastN; Color myColor = color; int myWidth = getWidth(); if (realWidth > 0 && paintSettings.isUseRealWidth() && !showDirection) { /* if we have a "width" tag, try use it */ /* (this might be slow and could be improved by caching the value in the Way, on the other hand only used if "real width" is enabled) */ String widthTag = w.get("width"); if(widthTag == null) { widthTag = w.get("est_width"); } if(widthTag != null) { try { realWidth = Integer.parseInt(widthTag); } catch(NumberFormatException nfe) { } } myWidth = (int) (100 / (float) (painter.getCircum() / realWidth)); if (myWidth < getWidth()) { myWidth = getWidth(); } } if(w.isHighlighted()) { myColor = paintSettings.getHighlightColor(); } else if (selected) { myColor = paintSettings.getSelectedColor(); } else if(w.isDisabled()) { myColor = paintSettings.getInactiveColor(); } /* draw overlays under the way */ if(overlays != null) { for(LineElemStyle s : overlays) { if(!s.over) { painter.drawWay(w, s.color != null && selected ? myColor: s.color, s.getWidth(myWidth), s.getDashed(), s.dashedColor, false, false, false); } } } /* draw the way */ painter.drawWay(w, myColor, myWidth, dashed, dashedColor, showDirection, selected ? false : reversedDirection, showOnlyHeadArrowOnly); /* draw overlays above the way */ if(overlays != null) { for(LineElemStyle s : overlays) { if(s.over) { painter.drawWay(w, s.color != null && selected ? myColor : s.color, s.getWidth(myWidth), s.getDashed(), s.dashedColor, false, false, false); } } } if(paintSettings.isShowOrderNumber()) { int orderNumber = 0; lastN = null; for(Node n : w.getNodes()) { if(lastN != null) { orderNumber++; painter.drawOrderNumber(lastN, n, orderNumber); } lastN = n; } } } public int getWidth() { if (width == -1) return MapPaintSettings.INSTANCE.getDefaultSegmentWidth(); return width; } public void setWidth(int width) { this.width = width; } }