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