// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui.mappaint.styleelement;
import java.util.Objects;
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.StyledMapRenderer;
import org.openstreetmap.josm.gui.mappaint.Cascade;
import org.openstreetmap.josm.gui.mappaint.Environment;
import org.openstreetmap.josm.gui.mappaint.Keyword;
import org.openstreetmap.josm.tools.CheckParameterUtil;
public class RepeatImageElement extends StyleElement {
/**
* The side on which the image should be aligned to the line.
*/
public enum LineImageAlignment {
TOP(.5),
CENTER(0),
BOTTOM(-.5);
private final double alignmentOffset;
LineImageAlignment(double alignmentOffset) {
this.alignmentOffset = alignmentOffset;
}
/**
* Gets the alignment offset.
* @return The offset relative to the image height compared to placing the image in the middle of the line.
*/
public double getAlignmentOffset() {
return alignmentOffset;
}
}
public MapImage pattern;
public float offset;
public float spacing;
public float phase;
public LineImageAlignment align;
private static final String[] REPEAT_IMAGE_KEYS = {REPEAT_IMAGE, REPEAT_IMAGE_WIDTH, REPEAT_IMAGE_HEIGHT, REPEAT_IMAGE_OPACITY,
null, null};
public RepeatImageElement(Cascade c, MapImage pattern, float offset, float spacing, float phase, LineImageAlignment align) {
super(c, 2.9f);
CheckParameterUtil.ensureParameterNotNull(pattern);
CheckParameterUtil.ensureParameterNotNull(align);
this.pattern = pattern;
this.offset = offset;
this.spacing = spacing;
this.phase = phase;
this.align = align;
}
public static RepeatImageElement create(Environment env) {
MapImage pattern = NodeElement.createIcon(env, REPEAT_IMAGE_KEYS);
if (pattern == null)
return null;
Cascade c = env.mc.getCascade(env.layer);
float offset = c.get(REPEAT_IMAGE_OFFSET, 0f, Float.class);
float spacing = c.get(REPEAT_IMAGE_SPACING, 0f, Float.class);
float phase = -c.get(REPEAT_IMAGE_PHASE, 0f, Float.class);
LineImageAlignment align = LineImageAlignment.CENTER;
Keyword alignKW = c.get(REPEAT_IMAGE_ALIGN, Keyword.CENTER, Keyword.class);
if ("top".equals(alignKW.val)) {
align = LineImageAlignment.TOP;
} else if ("bottom".equals(alignKW.val)) {
align = LineImageAlignment.BOTTOM;
}
return new RepeatImageElement(c, pattern, offset, spacing, phase, align);
}
@Override
public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter,
boolean selected, boolean outermember, boolean member) {
if (primitive instanceof Way) {
Way w = (Way) primitive;
painter.drawRepeatImage(w, pattern, painter.isInactiveMode() || w.isDisabled(), offset, spacing, phase, align);
}
}
@Override
public boolean isProperLineStyle() {
return true;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
if (!super.equals(obj)) return false;
RepeatImageElement that = (RepeatImageElement) obj;
return align == that.align &&
Float.compare(that.offset, offset) == 0 &&
Float.compare(that.spacing, spacing) == 0 &&
Float.compare(that.phase, phase) == 0 &&
Objects.equals(pattern, that.pattern);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), pattern, offset, spacing, phase, align);
}
@Override
public String toString() {
return "RepeatImageStyle{" + super.toString() + "pattern=[" + pattern +
"], offset=" + offset + ", spacing=" + spacing +
", phase=" + (-phase) + ", align=" + align + '}';
}
}