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.IPrimitive; 007import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings; 008import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer; 009import org.openstreetmap.josm.gui.mappaint.Cascade; 010import org.openstreetmap.josm.gui.mappaint.Environment; 011import org.openstreetmap.josm.gui.mappaint.Keyword; 012import org.openstreetmap.josm.gui.mappaint.styleelement.placement.PartiallyInsideAreaStrategy; 013import org.openstreetmap.josm.gui.mappaint.styleelement.placement.PositionForAreaStrategy; 014import org.openstreetmap.josm.tools.RotationAngle; 015 016/** 017 * This class defines how an icon is rendered onto the area. 018 * @author Michael Zangl 019 * @since 11730 020 */ 021public class AreaIconElement extends StyleElement { 022 /** 023 * The icon that is displayed on the center of the area. 024 */ 025 private final MapImage iconImage; 026 027 /** 028 * The rotation of the {@link #iconImageAngle} 029 */ 030 private final RotationAngle iconImageAngle; 031 032 /** 033 * The position of the icon inside the area. 034 */ 035 private final PositionForAreaStrategy iconPosition; 036 037 protected AreaIconElement(Cascade c, MapImage iconImage, RotationAngle iconImageAngle, PositionForAreaStrategy iconPosition) { 038 super(c, 4.8f); 039 this.iconImage = Objects.requireNonNull(iconImage, "iconImage"); 040 this.iconImageAngle = Objects.requireNonNull(iconImageAngle, "iconImageAngle"); 041 this.iconPosition = Objects.requireNonNull(iconPosition, "iconPosition"); 042 } 043 044 @Override 045 public void paintPrimitive(IPrimitive osm, MapPaintSettings paintSettings, StyledMapRenderer painter, 046 boolean selected, boolean outermember, boolean member) { 047 if (painter.isShowIcons()) { 048 painter.drawAreaIcon(osm, iconImage, painter.isInactiveMode() || osm.isDisabled(), selected, member, 049 iconImageAngle.getRotationAngle(osm), iconPosition); 050 } 051 } 052 053 /** 054 * Create a new {@link AreaIconElement} 055 * @param env The current style definitions 056 * @return The area element or <code>null</code> if there is no icon. 057 */ 058 public static AreaIconElement create(final Environment env) { 059 final Cascade c = env.mc.getCascade(env.layer); 060 MapImage iconImage = NodeElement.createIcon(env); 061 if (iconImage != null) { 062 RotationAngle rotationAngle = NodeElement.createRotationAngle(env); 063 Keyword positionKeyword = c.get(AreaElement.ICON_POSITION, null, Keyword.class); 064 PositionForAreaStrategy position = PositionForAreaStrategy.forKeyword(positionKeyword, PartiallyInsideAreaStrategy.INSTANCE); 065 066 return new AreaIconElement(c, iconImage, rotationAngle, position); 067 } else { 068 return null; 069 } 070 } 071 072 @Override 073 public int hashCode() { 074 final int prime = 31; 075 int result = super.hashCode(); 076 result = prime * result + ((iconImage == null) ? 0 : iconImage.hashCode()); 077 result = prime * result + ((iconImageAngle == null) ? 0 : iconImageAngle.hashCode()); 078 result = prime * result + ((iconPosition == null) ? 0 : iconPosition.hashCode()); 079 return result; 080 } 081 082 @Override 083 public boolean equals(Object obj) { 084 if (this == obj) { 085 return true; 086 } 087 if (!super.equals(obj)) { 088 return false; 089 } 090 if (getClass() != obj.getClass()) { 091 return false; 092 } 093 AreaIconElement other = (AreaIconElement) obj; 094 return Objects.equals(iconImage, other.iconImage) && 095 Objects.equals(iconImageAngle, other.iconImageAngle) && 096 Objects.equals(iconPosition, other.iconPosition); 097 } 098 099 @Override 100 public String toString() { 101 return "AreaIconElement{" + super.toString() + "iconImage=[" + iconImage + "] iconImageAngle=[" + iconImageAngle + "]}"; 102 } 103}