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