001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.mappaint;
003
004import static org.openstreetmap.josm.tools.Utils.equal;
005
006import org.openstreetmap.josm.data.osm.OsmPrimitive;
007import org.openstreetmap.josm.data.osm.Way;
008import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
009import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
010import org.openstreetmap.josm.tools.CheckParameterUtil;
011
012public class RepeatImageElemStyle extends ElemStyle implements StyleKeys {
013
014    public enum LineImageAlignment { TOP, CENTER, BOTTOM }
015
016    public MapImage pattern;
017    public float offset;
018    public float spacing;
019    public float phase;
020    public LineImageAlignment align;
021
022    public RepeatImageElemStyle(Cascade c, MapImage pattern, float offset, float spacing, float phase, LineImageAlignment align) {
023        super(c, 2.9f);
024        CheckParameterUtil.ensureParameterNotNull(pattern);
025        CheckParameterUtil.ensureParameterNotNull(align);
026        this.pattern = pattern;
027        this.offset = offset;
028        this.spacing = spacing;
029        this.phase = phase;
030        this.align = align;
031    }
032
033    public static RepeatImageElemStyle create(Environment env) {
034        MapImage pattern = NodeElemStyle.createIcon(env, REPEAT_IMAGE_KEYS);
035        if (pattern == null)
036            return null;
037        Cascade c = env.mc.getCascade(env.layer);
038        float offset = c.get(REPEAT_IMAGE_OFFSET, 0f, Float.class);
039        float spacing = c.get(REPEAT_IMAGE_SPACING, 0f, Float.class);
040        float phase = - c.get(REPEAT_IMAGE_PHASE, 0f, Float.class);
041
042        LineImageAlignment align = LineImageAlignment.CENTER;
043        Keyword alignKW = c.get(REPEAT_IMAGE_ALIGN, Keyword.CENTER, Keyword.class);
044        if (equal(alignKW.val, "top")) {
045            align = LineImageAlignment.TOP;
046        } else if (equal(alignKW.val, "bottom")) {
047            align = LineImageAlignment.BOTTOM;
048        }
049
050        return new RepeatImageElemStyle(c, pattern, offset, spacing, phase, align);
051    }
052
053    @Override
054    public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter, boolean selected, boolean member) {
055        Way w = (Way) primitive;
056        painter.drawRepeatImage(w, pattern.getImage(), offset, spacing, phase, align);
057    }
058
059    @Override
060    public boolean isProperLineStyle() {
061        return true;
062    }
063
064    @Override
065    public boolean equals(Object obj) {
066        if (obj == null || getClass() != obj.getClass())
067            return false;
068        if (!super.equals(obj))
069            return false;
070        final RepeatImageElemStyle other = (RepeatImageElemStyle) obj;
071        if (!this.pattern.equals(other.pattern)) return false;
072        if (this.offset != other.offset) return false;
073        if (this.spacing != other.spacing) return false;
074        if (this.phase != other.phase) return false;
075        if (this.align != other.align) return false;
076        return true;
077    }
078
079    @Override
080    public int hashCode() {
081        int hash = 7;
082        hash = 83 * hash + this.pattern.hashCode();
083        hash = 83 * hash + Float.floatToIntBits(this.offset);
084        hash = 83 * hash + Float.floatToIntBits(this.spacing);
085        hash = 83 * hash + Float.floatToIntBits(this.phase);
086        hash = 83 * hash + this.align.hashCode();
087        return hash;
088    }
089
090    @Override
091    public String toString() {
092        return "RepeatImageStyle{" + super.toString() + "pattern=[" + pattern +
093                "], offset=" + offset + ", spacing=" + spacing +
094                ", phase=" + (-phase) + ", align=" + align + "}";
095    }
096}