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.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(OsmPrimitive 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}