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}