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.getCascade();
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        return Objects.hash(super.hashCode(), iconImage, iconImageAngle, iconPosition);
075    }
076
077    @Override
078    public boolean equals(Object obj) {
079        if (this == obj) {
080            return true;
081        }
082        if (!super.equals(obj)) {
083            return false;
084        }
085        if (getClass() != obj.getClass()) {
086            return false;
087        }
088        AreaIconElement other = (AreaIconElement) obj;
089        return Objects.equals(iconImage, other.iconImage) &&
090                Objects.equals(iconImageAngle, other.iconImageAngle) &&
091                Objects.equals(iconPosition, other.iconPosition);
092    }
093
094    @Override
095    public String toString() {
096        return "AreaIconElement{" + super.toString() + "iconImage=[" + iconImage + "] iconImageAngle=[" + iconImageAngle + "]}";
097    }
098}