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