Index: src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java (revision 3980)
+++ src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java (working copy)
@@ -38,12 +38,11 @@
import org.openstreetmap.josm.gui.NavigatableComponent;
import org.openstreetmap.josm.gui.mappaint.NodeElemStyle;
import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.HorizontalTextAlignment;
-import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.Symbol;
import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.NodeTextElement;
+import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.Symbol;
import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.VerticalTextAlignment;
import org.openstreetmap.josm.gui.mappaint.TextElement;
import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.tools.LanguageInfo;
import org.openstreetmap.josm.tools.Pair;
public class MapPainter {
@@ -73,8 +72,6 @@
private final boolean leftHandTraffic;
- private final Collection regionalNameOrder;
-
private static final double PHI = Math.toRadians(20);
private static final double cosPHI = Math.cos(PHI);
private static final double sinPHI = Math.sin(PHI);
@@ -103,8 +100,6 @@
this.virtualNodeSpace = Main.pref.getInteger("mappaint.node.virtual-space", 70);
this.segmentNumberSpace = Main.pref.getInteger("mappaint.segmentnumber.space", 40);
- String[] names = {"name:" + LanguageInfo.getJOSMLocaleCode(), "name", "int_name", "ref", "operator", "brand", "addr:housenumber"};
- this.regionalNameOrder = Main.pref.getCollection("mappaint.nameOrder", Arrays.asList(names));
this.circum = circum;
this.leftHandTraffic = leftHandTraffic;
}
@@ -117,7 +112,7 @@
* e.g. oneway street or waterway
* @param onewayReversed for oneway=-1 and similar
*/
- public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor,
+ public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor,
TextElement text, boolean showOrientation, boolean showHeadArrowOnly,
boolean showOneway, boolean onewayReversed) {
@@ -252,7 +247,7 @@
private void drawTextOnPath(Way way, TextElement text) {
if (text == null)
return;
- String name = text.getString(way, this);
+ String name = text.getString(way);
if (name == null || name.equals(""))
return;
@@ -291,8 +286,8 @@
double tStart;
if (p1[0] < p2[0] &&
- p1[2] < Math.PI/2 &&
- p1[2] > -Math.PI/2) {
+ p1[2] < Math.PI/2 &&
+ p1[2] > -Math.PI/2) {
angleOffset = 0;
offsetSign = 1;
tStart = t1;
@@ -346,8 +341,8 @@
continue;
}
return new double[] {poly.xpoints[i-1]+(totalLen - curLen)/segLen*dx,
- poly.ypoints[i-1]+(totalLen - curLen)/segLen*dy,
- Math.atan2(dy, dx)};
+ poly.ypoints[i-1]+(totalLen - curLen)/segLen*dy,
+ Math.atan2(dy, dx)};
}
return null;
}
@@ -494,9 +489,12 @@
if (!isShowNames() || text == null)
return;
- String s = text.textKey == null ? getNodeName(n) : n.get(text.textKey);
- if (s == null)
- return;
+ /*
+ * abort if we can't compose the label to be rendered
+ */
+ if (text.labelCompositionStrategy == null) return;
+ String s = text.labelCompositionStrategy.compose(n);
+ if (s == null) return;
Font defaultFont = g.getFont();
g.setFont(text.font);
@@ -597,9 +595,12 @@
}
if (text != null && isShowNames()) {
- String name = text.textKey == null ? getAreaName(osm) : osm.get(text.textKey);
- if (name == null)
- return;
+ /*
+ * abort if we can't compose the label to be rendered
+ */
+ if (text.labelCompositionStrategy == null) return;
+ String name = text.labelCompositionStrategy.compose(osm);
+ if (name == null) return;
Rectangle pb = polygon.getBounds();
FontMetrics fontMetrics = g.getFontMetrics(orderFont); // if slow, use cache
@@ -930,34 +931,6 @@
}
}
- //TODO Not a good place for this method
- public String getNodeName(Node n) {
- String name = null;
- if (n.hasKeys()) {
- for (String rn : regionalNameOrder) {
- name = n.get(rn);
- if (name != null) {
- break;
- }
- }
- }
- return name;
- }
-
- //TODO Not a good place for this method
- public String getAreaName(OsmPrimitive w) {
- String name = null;
- if (w.hasKeys()) {
- for (String rn : regionalNameOrder) {
- name = w.get(rn);
- if (name != null) {
- break;
- }
- }
- }
- return name;
- }
-
public boolean isInactive() {
return inactive;
}
Index: src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java (revision 3980)
+++ src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java (working copy)
@@ -16,7 +16,7 @@
public float z_index;
public float object_z_index;
public boolean isModifier; // false, if style can serve as main style for the
- // primitive; true, if it is a highlight or modifier
+ // primitive; true, if it is a highlight or modifier
public ElemStyle(float z_index, float object_z_index, boolean isModifier) {
this.z_index = z_index;
@@ -63,7 +63,7 @@
String name = c.get("font-family", Main.pref.get("mappaint.font", "Helvetica"), String.class);
float size = c.get("font-size", (float) Main.pref.getInteger("mappaint.fontsize", 8), Float.class);
int weight = Font.PLAIN;
- Keyword weightKW = c.get("font-wheight", null, Keyword.class);
+ Keyword weightKW = c.get("font-weight", null, Keyword.class);
if (weightKW != null && equal(weightKW, "bold")) {
weight = Font.BOLD;
}
Index: src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java (revision 0)
+++ src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java (revision 0)
@@ -0,0 +1,244 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.tools.LanguageInfo;
+
+/**
+ * Provides an abstract parent class and three concrete sub classes for various
+ * strategies on how to compose the text label which can be rendered close to a node
+ * or within an area in an OSM map.
+ *
+ * The three strategies below support three rules for composing a label:
+ *
+ * - {@link StaticLabelCompositionStrategy} - the label is given by a static text
+ * specified in the MapCSS style file
+ *
+ * - {@link TagLookupCompositionStrategy} - the label is given by the content of a
+ * tag whose name specified in the MapCSS style file
+ *
+ * - {@link DeriveLabelFromNameTagsCompositionStrategy} - the label is given by the value
+ * of one
+ * of the configured "name tags". The list of relevant name tags can be configured
+ * in the JOSM preferences
+ * content of a tag whose name specified in the MapCSS style file, see the preference
+ * option mappaint.nameOrder.
+ *
+ *
+ *
+ */
+public abstract class LabelCompositionStrategy {
+
+ static public class StaticLabelCompositionStrategy extends LabelCompositionStrategy {
+ private String defaultLabel;
+ public StaticLabelCompositionStrategy(String defaultLabel){
+ this.defaultLabel = defaultLabel;
+ }
+
+ @Override
+ public String compose(OsmPrimitive primitive) {
+ return defaultLabel;
+ }
+
+ public String getDefaultLabel() {
+ return defaultLabel;
+ }
+
+ @Override
+ public String toString() {
+ return "{" + getClass().getSimpleName() + " defaultLabel=" + defaultLabel + "}";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((defaultLabel == null) ? 0 : defaultLabel.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ StaticLabelCompositionStrategy other = (StaticLabelCompositionStrategy) obj;
+ if (defaultLabel == null) {
+ if (other.defaultLabel != null)
+ return false;
+ } else if (!defaultLabel.equals(other.defaultLabel))
+ return false;
+ return true;
+ }
+ }
+
+ static public class TagLookupCompositionStrategy extends LabelCompositionStrategy {
+
+ private String defaultLabelTag;
+ public TagLookupCompositionStrategy(String defaultLabelTag){
+ if (defaultLabelTag != null) {
+ defaultLabelTag = defaultLabelTag.trim();
+ if (defaultLabelTag.isEmpty()) {
+ defaultLabelTag = null;
+ }
+ }
+ this.defaultLabelTag = defaultLabelTag;
+ }
+
+ @Override
+ public String compose(OsmPrimitive primitive) {
+ if (defaultLabelTag == null) return null;
+ if (primitive == null) return null;
+ return primitive.get(defaultLabelTag);
+ }
+
+ public String getDefaultLabelTag() {
+ return defaultLabelTag;
+ }
+
+ @Override
+ public String toString() {
+ return "{" + getClass().getSimpleName() + " defaultLabelTag=" + defaultLabelTag + "}";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((defaultLabelTag == null) ? 0 : defaultLabelTag.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ TagLookupCompositionStrategy other = (TagLookupCompositionStrategy) obj;
+ if (defaultLabelTag == null) {
+ if (other.defaultLabelTag != null)
+ return false;
+ } else if (!defaultLabelTag.equals(other.defaultLabelTag))
+ return false;
+ return true;
+ }
+ }
+
+ static public class DeriveLabelFromNameTagsCompositionStrategy extends LabelCompositionStrategy {
+
+ /**
+ * The list of default name tags from which a label candidate is derived.
+ */
+ static public final String[] DEFAULT_NAME_TAGS = {
+ "name:" + LanguageInfo.getJOSMLocaleCode(),
+ "name",
+ "int_name",
+ "ref",
+ "operator",
+ "brand",
+ "addr:housenumber"
+ };
+
+ private List nameTags = new ArrayList();
+
+ /**
+ * Creates the strategy and initializes its name tags from the preferences.
+ *
+ * Note: If the list of name tags in the preferences changes, strategy instances
+ * are not notified. It's up to the client to listen to preference changes and
+ * invoke {@link #initNameTagsFromPreferences()} accordingly.
+ *
+ */
+ public DeriveLabelFromNameTagsCompositionStrategy() {
+ initNameTagsFromPreferences();
+ }
+
+ /**
+ * Sets the name tags to be looked up in order to build up the label
+ *
+ * @param nameTags the name tags. null values are ignore.
+ */
+ public void setNameTags(List nameTags){
+ if (nameTags == null) {
+ nameTags = Collections.emptyList();
+ }
+ this.nameTags = new ArrayList();
+ for(String tag: nameTags) {
+ if (tag == null) {
+ continue;
+ }
+ tag = tag.trim();
+ if (tag.isEmpty()) {
+ continue;
+ }
+ this.nameTags.add(tag);
+ }
+ }
+
+ /**
+ * Replies an unmodifiable list of the name tags used to compose the label.
+ *
+ * @return the list of name tags
+ */
+ public List getNameTags() {
+ return Collections.unmodifiableList(nameTags);
+ }
+
+ /**
+ * Initializes the name tags to use from a list of default name tags (see
+ * {@link #DEFAULT_NAME_TAGS}) and from name tags configured in the preferences
+ * using the preference key mappaint.nameOrder.
+ */
+ public void initNameTagsFromPreferences() {
+ if (Main.pref == null){
+ this.nameTags = new ArrayList(Arrays.asList(DEFAULT_NAME_TAGS));
+ } else {
+ this.nameTags = new ArrayList(
+ Main.pref.getCollection("mappaint.nameOrder", Arrays.asList(DEFAULT_NAME_TAGS))
+ );
+ }
+ }
+
+ private String getPrimitiveName(OsmPrimitive n) {
+ String name = null;
+ if (!n.hasKeys()) return null;
+ for (String rn : nameTags) {
+ name = n.get(rn);
+ if (name != null) return name;
+ }
+ return null;
+ }
+
+ @Override
+ public String compose(OsmPrimitive primitive) {
+ if (primitive == null) return null;
+ return getPrimitiveName(primitive);
+ }
+
+ @Override
+ public String toString() {
+ return "{" + getClass().getSimpleName() +"}";
+ }
+ }
+
+ /**
+ * Replies the text value to be rendered as label for the primitive {@code primitive}.
+ *
+ * @param primitive the primitive
+ *
+ * @return the text value to be rendered or null, if primitive is null or
+ * if no suitable value could be composed
+ */
+ abstract public String compose(OsmPrimitive primitive);
+}
Index: src/org/openstreetmap/josm/gui/mappaint/MultiCascade.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/MultiCascade.java (revision 3980)
+++ src/org/openstreetmap/josm/gui/mappaint/MultiCascade.java (working copy)
@@ -6,13 +6,15 @@
import java.util.Map;
import java.util.Map.Entry;
+import org.openstreetmap.josm.tools.CheckParameterUtil;
+
/**
* Several layers / cascades, e.g. one for the main Line and one for each overlay.
* The range is (0,Infinity) at first and it shrinks in the process when
* StyleSources apply zoom level dependent properties.
*/
public class MultiCascade {
-
+
private Map layers;
public Range range;
@@ -27,8 +29,7 @@
* a clone of the "*" layer, if it exists.
*/
public Cascade getOrCreateCascade(String layer) {
- if (layer == null)
- throw new IllegalArgumentException();
+ CheckParameterUtil.ensureParameterNotNull(layer);
Cascade c = layers.get(layer);
if (c == null) {
if (layers.containsKey("*")) {
Index: src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java (revision 3980)
+++ src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java (working copy)
@@ -25,6 +25,7 @@
* applies for Nodes and turn restriction relations
*/
public class NodeElemStyle extends ElemStyle {
+ //static private final Logger logger = Logger.getLogger(NodeElemStyle.class.getName());
public ImageIcon icon;
public int iconAlpha;
@@ -62,10 +63,10 @@
return false;
final Symbol other = (Symbol) obj;
return symbol == other.symbol &&
- size == other.size &&
- equal(stroke, other.stroke) &&
- equal(strokeColor, other.strokeColor) &&
- equal(fillColor, other.fillColor);
+ size == other.size &&
+ equal(stroke, other.stroke) &&
+ equal(strokeColor, other.strokeColor) &&
+ equal(fillColor, other.fillColor);
}
@Override
@@ -82,8 +83,8 @@
@Override
public String toString() {
return "symbol=" + symbol + " size=" + size +
- (stroke != null ? (" stroke=" + stroke + " strokeColor=" + strokeColor) : "") +
- (fillColor != null ? (" fillColor=" + fillColor) : "");
+ (stroke != null ? (" stroke=" + stroke + " strokeColor=" + strokeColor) : "") +
+ (fillColor != null ? (" fillColor=" + fillColor) : "");
}
}
@@ -107,7 +108,7 @@
return false;
final NodeTextElement other = (NodeTextElement) obj;
return hAlign == other.hAlign &&
- vAlign == other.vAlign;
+ vAlign == other.vAlign;
}
@Override
@@ -162,9 +163,6 @@
symbol = createSymbol(env);
}
- if (icon == null && symbol == null && !allowOnlyText)
- return null;
-
NodeTextElement text = null;
TextElement te = TextElement.create(c, PaintColors.TEXT.get());
if (te != null) {
@@ -192,7 +190,7 @@
}
text = new NodeTextElement(te, hAlign, vAlign);
}
-
+
return new NodeElemStyle(c, icon, iconAlpha, symbol, text);
}
@@ -224,7 +222,7 @@
shape = SymbolShape.DECAGON;
} else
return null;
-
+
Float sizeOnDefault = c_def.get("symbol-size", null, Float.class);
if (sizeOnDefault != null && sizeOnDefault <= 0) {
sizeOnDefault = null;
@@ -258,8 +256,9 @@
}
Color fillColor = c.get("symbol-fill-color", null, Color.class);
- if (stroke == null && fillColor == null)
+ if (stroke == null && fillColor == null) {
fillColor = Color.BLUE;
+ }
if (fillColor != null) {
float fillAlpha = c.get("symbol-fill-opacity", 1f, Float.class);
@@ -335,14 +334,14 @@
}
final int size = Utils.max((selected ? settings.getSelectedNodeSize() : 0),
- (n.isTagged() ? settings.getTaggedNodeSize() : 0),
- (isConnection ? settings.getConnectionNodeSize() : 0),
- settings.getUnselectedNodeSize());
+ (n.isTagged() ? settings.getTaggedNodeSize() : 0),
+ (isConnection ? settings.getConnectionNodeSize() : 0),
+ settings.getUnselectedNodeSize());
final boolean fill = (selected && settings.isFillSelectedNode()) ||
- (n.isTagged() && settings.isFillTaggedNode()) ||
- (isConnection && settings.isFillConnectionNode()) ||
- settings.isFillUnselectedNode();
+ (n.isTagged() && settings.isFillTaggedNode()) ||
+ (isConnection && settings.isFillConnectionNode()) ||
+ settings.isFillUnselectedNode();
painter.drawNode(n, color, size, fill, text);
}
@@ -394,8 +393,8 @@
@Override
public String toString() {
return "NodeElemStyle{" + super.toString() +
- (icon != null ? ("icon=" + icon + " iconAlpha=" + iconAlpha) : "") +
- (symbol != null ? (" symbol=[" + symbol + "]") : "") + '}';
+ (icon != null ? ("icon=" + icon + " iconAlpha=" + iconAlpha) : "") +
+ (symbol != null ? (" symbol=[" + symbol + "]") : "") + '}';
}
}
Index: src/org/openstreetmap/josm/gui/mappaint/TextElement.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/TextElement.java (revision 3980)
+++ src/org/openstreetmap/josm/gui/mappaint/TextElement.java (working copy)
@@ -1,31 +1,53 @@
// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui.mappaint;
-import static org.openstreetmap.josm.tools.Utils.equal;
-
import java.awt.Color;
import java.awt.Font;
+
import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.visitor.paint.MapPainter;
-
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.DeriveLabelFromNameTagsCompositionStrategy;
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.StaticLabelCompositionStrategy;
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.TagLookupCompositionStrategy;
import org.openstreetmap.josm.tools.CheckParameterUtil;
import org.openstreetmap.josm.tools.Utils;
+/**
+ * Represents the rendering style for a textual label placed somewhere on the map.
+ *
+ */
public class TextElement {
- // textKey == null means automatic generation of text string, otherwise
- // the corresponding tag value is used
- public String textKey;
+ //static private final Logger logger = Logger.getLogger(TextElement.class.getName());
+
+ static private final LabelCompositionStrategy AUTO_LABEL_COMPOSITION_STRATEGY = new DeriveLabelFromNameTagsCompositionStrategy();
+
+ /** the font to be used when rendering*/
public Font font;
public int xOffset;
public int yOffset;
public Color color;
public Float haloRadius;
public Color haloColor;
+ /** the strategy for building the actual label value for a given a {@link OsmPrimitive}.
+ * Check for null before accessing.
+ */
+ public LabelCompositionStrategy labelCompositionStrategy;
- public TextElement(String textKey, Font font, int xOffset, int yOffset, Color color, Float haloRadius, Color haloColor) {
+ /**
+ * Creates a new text element
+ *
+ * @param strategy the strategy indicating how the text is composed for a specific {@link OsmPrimitive} to be rendered.
+ * If null, no label is rendered.
+ * @param font the font to be used. Must not be null.
+ * @param xOffset
+ * @param yOffset
+ * @param color the color to be used. Must not be null
+ * @param haloRadius
+ * @param haloColor
+ */
+ public TextElement(LabelCompositionStrategy strategy, Font font, int xOffset, int yOffset, Color color, Float haloRadius, Color haloColor) {
CheckParameterUtil.ensureParameterNotNull(font);
CheckParameterUtil.ensureParameterNotNull(color);
- this.textKey = textKey;
+ labelCompositionStrategy = strategy;
this.font = font;
this.xOffset = xOffset;
this.yOffset = yOffset;
@@ -34,8 +56,13 @@
this.haloColor = haloColor;
}
+ /**
+ * Copy constructor
+ *
+ * @param other the other element.
+ */
public TextElement(TextElement other) {
- this.textKey = other.textKey;
+ this.labelCompositionStrategy = other.labelCompositionStrategy;
this.font = other.font;
this.xOffset = other.xOffset;
this.yOffset = other.yOffset;
@@ -44,17 +71,47 @@
this.haloRadius = other.haloRadius;
}
- public static TextElement create(Cascade c, Color defTextColor) {
-
- String textKey = null;
+ /**
+ * Derives a suitable label composition strategy from the style properties in
+ * {@code c}.
+ *
+ * @param c the style properties
+ * @return the label composition strategy
+ */
+ protected static LabelCompositionStrategy buildLabelCompositionStrategy(Cascade c){
+ LabelCompositionStrategy strategy;
Keyword textKW = c.get("text", null, Keyword.class, true);
if (textKW == null) {
- textKey = c.get("text", null, String.class);
- if (textKey == null)
- return null;
+ String textKey = c.get("text", null, String.class);
+ if (textKey == null) return null;
+ strategy = new StaticLabelCompositionStrategy(textKey);
} else if (!textKW.val.equals("auto"))
return null;
+ else {
+ String defaultLabelTag = c.get("text-from-tag", null, String.class);
+ if (defaultLabelTag == null){
+ strategy = AUTO_LABEL_COMPOSITION_STRATEGY;
+ } else {
+ strategy = new TagLookupCompositionStrategy(defaultLabelTag);
+ }
+ }
+ return strategy;
+ }
+ /**
+ * Builds a text element from style properties in {@code c} and the
+ * default text color {@code defaultTextColor}
+ *
+ * @param c the style properties
+ * @param defaultTextColor the default text color. Must not be null.
+ * @return the text element or null, if the style properties don't include
+ * properties for text rendering
+ * @throws IllegalArgumentException thrown if {@code defaultTextColor} is null
+ */
+ public static TextElement create(Cascade c, Color defaultTextColor) throws IllegalArgumentException{
+ CheckParameterUtil.ensureParameterNotNull(defaultTextColor, "defaultTextColor");
+
+ LabelCompositionStrategy strategy = buildLabelCompositionStrategy(c);
Font font = ElemStyle.getFont(c);
float xOffset = 0;
@@ -70,8 +127,8 @@
}
xOffset = c.get("text-offset-x", xOffset, Float.class);
yOffset = c.get("text-offset-y", yOffset, Float.class);
-
- Color color = c.get("text-color", defTextColor, Color.class);
+
+ Color color = c.get("text-color", defaultTextColor, Color.class);
float alpha = c.get("text-opacity", 1f, Float.class);
color = new Color(color.getRed(), color.getGreen(),
color.getBlue(), Utils.color_float2int(alpha));
@@ -88,42 +145,86 @@
haloColor.getBlue(), Utils.color_float2int(haloAlpha));
}
- return new TextElement(textKey, font, (int) xOffset, - (int) yOffset, color, haloRadius, haloColor);
+ return new TextElement(strategy, font, (int) xOffset, - (int) yOffset, color, haloRadius, haloColor);
}
+ /**
+ * Replies the label to be rendered for the primitive {@code osm}.
+ *
+ * @param osm the the OSM object
+ * @return the label, or null, if {@code osm} is null or if no label can be
+ * derived for {@code osm}
+ */
+ public String getString(OsmPrimitive osm) {
+ if (labelCompositionStrategy == null) return null;
+ return labelCompositionStrategy.compose(osm);
+ }
+
@Override
- public boolean equals(Object obj) {
- if (obj == null || getClass() != obj.getClass())
- return false;
- final TextElement other = (TextElement) obj;
- return equal(textKey, other.textKey) &&
- equal(font, other.font) &&
- xOffset == other.xOffset &&
- yOffset == other.yOffset &&
- equal(color, other.color) &&
- equal(haloRadius, other.haloRadius) &&
- equal(haloColor, other.haloColor);
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{TextElement ");
+ sb.append("strategy=");
+ sb.append(labelCompositionStrategy == null ? "null" : labelCompositionStrategy.toString());
+ sb.append("}");
+ return sb.toString();
}
+ /* -------------------------------------------------------------------------------- */
+ /* equals and hashCode (generated by Eclipse, regenerate if necessary) */
+ /* -------------------------------------------------------------------------------- */
@Override
public int hashCode() {
- int hash = 3;
- hash = 79 * hash + (textKey != null ? textKey.hashCode() : 0);
- hash = 79 * hash + font.hashCode();
- hash = 79 * hash + xOffset;
- hash = 79 * hash + yOffset;
- hash = 79 * hash + color.hashCode();
- hash = 79 * hash + (haloRadius != null ? Float.floatToIntBits(haloRadius) : 0);
- hash = 79 * hash + (haloColor != null ? haloColor.hashCode() : 0);
- return hash;
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((color == null) ? 0 : color.hashCode());
+ result = prime * result + ((font == null) ? 0 : font.hashCode());
+ result = prime * result + ((haloColor == null) ? 0 : haloColor.hashCode());
+ result = prime * result + ((haloRadius == null) ? 0 : haloRadius.hashCode());
+ result = prime * result + ((labelCompositionStrategy == null) ? 0 : labelCompositionStrategy.hashCode());
+ result = prime * result + xOffset;
+ result = prime * result + yOffset;
+ return result;
}
- public String getString(OsmPrimitive osm, MapPainter painter) {
- if (textKey == null)
- return painter.getAreaName(osm);
- else
- return osm.get(textKey);
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ TextElement other = (TextElement) obj;
+ if (color == null) {
+ if (other.color != null)
+ return false;
+ } else if (!color.equals(other.color))
+ return false;
+ if (font == null) {
+ if (other.font != null)
+ return false;
+ } else if (!font.equals(other.font))
+ return false;
+ if (haloColor == null) {
+ if (other.haloColor != null)
+ return false;
+ } else if (!haloColor.equals(other.haloColor))
+ return false;
+ if (haloRadius == null) {
+ if (other.haloRadius != null)
+ return false;
+ } else if (!haloRadius.equals(other.haloRadius))
+ return false;
+ if (labelCompositionStrategy == null) {
+ if (other.labelCompositionStrategy != null)
+ return false;
+ } else if (!labelCompositionStrategy.equals(other.labelCompositionStrategy))
+ return false;
+ if (xOffset != other.xOffset)
+ return false;
+ if (yOffset != other.yOffset)
+ return false;
+ return true;
}
-
-
}
Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java (revision 3980)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java (working copy)
@@ -27,7 +27,8 @@
import org.openstreetmap.josm.tools.Utils;
public class MapCSSStyleSource extends StyleSource {
-
+ //static private final Logger logger = Logger.getLogger(MapCSSStyleSource.class.getName());
+
final public List rules;
private Color backgroundColorOverride;
@@ -65,6 +66,7 @@
}
}
+ @Override
public InputStream getSourceInputStream() throws IOException {
MirroredInputStream in = new MirroredInputStream(url);
InputStream zip = in.getZipEntry("mapcss", "style");
@@ -107,26 +109,28 @@
Environment env = new Environment(n, mc, "default", this);
NEXT_RULE:
- for (MapCSSRule r : rules) {
- for (Selector s : r.selectors) {
- if ((s instanceof GeneralSelector)) {
- GeneralSelector gs = (GeneralSelector) s;
- if (gs.base.equals(type))
- {
- for (Condition cnd : gs.conds) {
- if (!cnd.applies(env))
- continue NEXT_RULE;
+ for (MapCSSRule r : rules) {
+ for (Selector s : r.selectors) {
+ if ((s instanceof GeneralSelector)) {
+ GeneralSelector gs = (GeneralSelector) s;
+ if (gs.base.equals(type))
+ {
+ for (Condition cnd : gs.conds) {
+ if (!cnd.applies(env)) {
+ continue NEXT_RULE;
+ }
+ }
+ for (Instruction i : r.declaration) {
+ i.execute(env);
+ }
}
- for (Instruction i : r.declaration) {
- i.execute(env);
- }
}
}
}
- }
return mc.getCascade("default");
}
+ @Override
public Color getBackgroundColorOverride() {
return backgroundColorOverride;
}
@@ -159,7 +163,7 @@
i.execute(env);
}
}
- }
+ }
env.layer = sub;
for (Instruction i : r.declaration) {
i.execute(env);
Index: test/data/styles/label-from-tag.mapcss
===================================================================
--- test/data/styles/label-from-tag.mapcss (revision 0)
+++ test/data/styles/label-from-tag.mapcss (revision 0)
@@ -0,0 +1,21 @@
+/*
+ * Simple test style sheet. Includes a style with the new style declaration 'text-from-tag'.
+ *
+ */
+
+meta {
+ title: "Test style - Deriving labels from tags";
+}
+
+canvas {
+ background-color: #000000;
+}
+
+node {
+ text: auto;
+ text-color: white;
+ font-size: 12;
+ /* the value of the tag 'my_label_tag' will be rendered as text */
+ text-from-tag: my_label_tag;
+}
+
Index: test/functional/org/openstreetmap/josm/fixtures/JOSMFixture.java
===================================================================
--- test/functional/org/openstreetmap/josm/fixtures/JOSMFixture.java (revision 3980)
+++ test/functional/org/openstreetmap/josm/fixtures/JOSMFixture.java (working copy)
@@ -10,7 +10,7 @@
import java.util.logging.Logger;
import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.osm.DataSetMergerTest;
+import org.openstreetmap.josm.data.Preferences;
import org.openstreetmap.josm.data.projection.Mercator;
import org.openstreetmap.josm.io.OsmApi;
import org.openstreetmap.josm.tools.I18n;
@@ -39,7 +39,7 @@
// load properties
//
try {
- testProperties.load(DataSetMergerTest.class.getResourceAsStream(testPropertiesResourceName));
+ testProperties.load(JOSMFixture.class.getResourceAsStream(testPropertiesResourceName));
} catch(Exception e){
logger.log(Level.SEVERE, MessageFormat.format("failed to load property file ''{0}''", testPropertiesResourceName));
fail(MessageFormat.format("failed to load property file ''{0}''. \nMake sure the path ''$project_root/test/config'' is on the classpath.", testPropertiesResourceName));
@@ -57,6 +57,7 @@
}
}
System.setProperty("josm.home", josmHome);
+ Main.pref = new Preferences();
I18n.init();
// initialize the plaform hook, and
Main.determinePlatformHook();
Index: test/unit/org/openstreetmap/josm/gui/mappaint/AllMappaintTests.groovy
===================================================================
--- test/unit/org/openstreetmap/josm/gui/mappaint/AllMappaintTests.groovy (revision 0)
+++ test/unit/org/openstreetmap/josm/gui/mappaint/AllMappaintTests.groovy (revision 0)
@@ -0,0 +1,15 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint
+
+import junit.framework.TestCase;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses([
+ LabelCompositionStrategyTest.class,
+ MapCSSWithExtendedTextDirectivesTest.class
+])
+public class AllMappaintTests extends TestCase{}
+
Index: test/unit/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategyTest.groovy
===================================================================
--- test/unit/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategyTest.groovy (revision 0)
+++ test/unit/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategyTest.groovy (revision 0)
@@ -0,0 +1,66 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint
+
+import org.junit.*
+import org.openstreetmap.josm.fixtures.JOSMFixture;
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.DeriveLabelFromNameTagsCompositionStrategy
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.StaticLabelCompositionStrategy;
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.TagLookupCompositionStrategy
+import org.openstreetmap.josm.data.osm.Node;
+
+class LabelCompositionStrategyTest {
+
+ @BeforeClass
+ public static void createJOSMFixture(){
+ JOSMFixture.createUnitTestFixture().init()
+ }
+
+ @Test
+ public void createStaticLabelCompositionStrategy() {
+ def n = new Node()
+
+ def strat = new StaticLabelCompositionStrategy(null)
+ assert strat.compose(n) == null
+
+ strat = new StaticLabelCompositionStrategy("a label")
+ assert strat.compose(n) == "a label"
+ }
+
+ @Test
+ public void createTagLookupCompositionStrategy() {
+ def n = new Node()
+ n.put("my-tag", "my-value")
+
+ def strat = new TagLookupCompositionStrategy(null)
+ assert strat.compose(n) == null
+
+ strat = new TagLookupCompositionStrategy("name")
+ assert strat.compose(n) == null
+
+ strat = new TagLookupCompositionStrategy("my-tag")
+ assert strat.compose(n) == "my-value"
+ }
+
+ @Test
+ public void createDeriveLabelFromNameTagsCompositionStrategy() {
+ def n
+ def strat
+
+ strat = new DeriveLabelFromNameTagsCompositionStrategy()
+ strat.setNameTags(null)
+ assert strat.getNameTags() == []
+
+ strat = new DeriveLabelFromNameTagsCompositionStrategy()
+ strat.setNameTags(["name", "brand"])
+ assert strat.getNameTags() == ["name", "brand"]
+
+ n = new Node()
+ n.put("brand", "my brand")
+ assert strat.compose(n) == "my brand"
+
+ n = new Node()
+ n.put("name", "my name")
+ n.put("brand", "my brand")
+ assert strat.compose(n) == "my name"
+ }
+}
Index: test/unit/org/openstreetmap/josm/gui/mappaint/MapCSSWithExtendedTextDirectivesTest.groovy
===================================================================
--- test/unit/org/openstreetmap/josm/gui/mappaint/MapCSSWithExtendedTextDirectivesTest.groovy (revision 0)
+++ test/unit/org/openstreetmap/josm/gui/mappaint/MapCSSWithExtendedTextDirectivesTest.groovy (revision 0)
@@ -0,0 +1,58 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint
+
+import java.awt.Color;
+
+import org.junit.*;
+import org.openstreetmap.josm.fixtures.JOSMFixture
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.DeriveLabelFromNameTagsCompositionStrategy
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.StaticLabelCompositionStrategy
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.TagLookupCompositionStrategy
+class MapCSSWithExtendedTextDirectivesTest {
+
+
+ @BeforeClass
+ public static void createJOSMFixture(){
+ JOSMFixture.createUnitTestFixture().init()
+ }
+
+ @Test
+ public void createAutoTextElement() {
+ Cascade c = new Cascade()
+ c.put("text", new Keyword("auto"))
+
+ TextElement te = TextElement.create(c, Color.WHITE)
+ assert te.labelCompositionStrategy != null
+ assert te.labelCompositionStrategy instanceof DeriveLabelFromNameTagsCompositionStrategy
+ }
+
+ @Test
+ public void createTextElementComposingTextFromTag() {
+ Cascade c = new Cascade()
+ c.put("text", new Keyword("auto"))
+ c.put("text-from-tag", "my_name")
+
+ TextElement te = TextElement.create(c, Color.WHITE)
+ assert te.labelCompositionStrategy != null
+ assert te.labelCompositionStrategy instanceof TagLookupCompositionStrategy
+ assert te.labelCompositionStrategy.getDefaultLabelTag() == "my_name"
+ }
+
+ @Test
+ public void createTextElementWithStaticText() {
+ Cascade c = new Cascade()
+ c.put("text","my static label")
+
+ TextElement te = TextElement.create(c, Color.WHITE)
+ assert te.labelCompositionStrategy != null
+ assert te.labelCompositionStrategy instanceof StaticLabelCompositionStrategy
+ }
+
+ @Test
+ public void createNullStrategy() {
+ Cascade c = new Cascade()
+
+ TextElement te = TextElement.create(c, Color.WHITE)
+ assert te.labelCompositionStrategy == null
+ }
+}