001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.mappaint.styleelement;
003
004import java.awt.Color;
005import java.util.Objects;
006
007import org.openstreetmap.josm.Main;
008import org.openstreetmap.josm.data.osm.OsmPrimitive;
009import org.openstreetmap.josm.data.osm.Relation;
010import org.openstreetmap.josm.data.osm.Way;
011import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
012import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
013import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
014import org.openstreetmap.josm.gui.mappaint.Cascade;
015import org.openstreetmap.josm.gui.mappaint.Environment;
016import org.openstreetmap.josm.gui.mappaint.Keyword;
017import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
018import org.openstreetmap.josm.tools.CheckParameterUtil;
019import org.openstreetmap.josm.tools.Utils;
020
021public class AreaElement extends StyleElement {
022
023    /**
024     * If fillImage == null, color is the fill-color, otherwise
025     * an arbitrary color value sampled from the fillImage
026     */
027    public Color color;
028    public MapImage fillImage;
029    public TextLabel text;
030    public Float extent;
031    public Float extentThreshold;
032
033    protected AreaElement(Cascade c, Color color, MapImage fillImage, Float extent, Float extentThreshold, TextLabel text) {
034        super(c, 1f);
035        CheckParameterUtil.ensureParameterNotNull(color);
036        this.color = color;
037        this.fillImage = fillImage;
038        this.extent = extent;
039        this.extentThreshold = extentThreshold;
040        this.text = text;
041    }
042
043    public static AreaElement create(final Environment env) {
044        final Cascade c = env.mc.getCascade(env.layer);
045        MapImage fillImage = null;
046        Color color;
047
048        IconReference iconRef = c.get(FILL_IMAGE, null, IconReference.class);
049        if (iconRef != null) {
050            fillImage = new MapImage(iconRef.iconName, iconRef.source, false);
051
052            color = new Color(fillImage.getImage(false).getRGB(
053                    fillImage.getWidth() / 2, fillImage.getHeight() / 2)
054            );
055
056            fillImage.alpha = Math.min(255, Math.max(0, Main.pref.getInteger("mappaint.fill-image-alpha", 255)));
057            Integer pAlpha = Utils.colorFloat2int(c.get(FILL_OPACITY, null, float.class));
058            if (pAlpha != null) {
059                fillImage.alpha = pAlpha;
060            }
061        } else {
062            color = c.get(FILL_COLOR, null, Color.class);
063            if (color != null) {
064                int alpha = color.getAlpha();
065                if (alpha == 255) {
066                    // Assume alpha value has not been specified by the user if
067                    // is set to fully opaque. Use default value in this case.
068                    // It is not an ideal solution, but a little tricky to get this
069                    // right, especially as named map colors can be changed in
070                    // the preference GUI and written to the preferences file.
071                    alpha = Math.min(255, Math.max(0, Main.pref.getInteger("mappaint.fillalpha", 50)));
072                }
073                Integer pAlpha = Utils.colorFloat2int(c.get(FILL_OPACITY, null, float.class));
074                if (pAlpha != null) {
075                    alpha = pAlpha;
076                }
077                color = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
078            }
079        }
080
081        TextLabel text = null;
082        Keyword textPos = c.get(TEXT_POSITION, null, Keyword.class);
083        if (textPos == null || "center".equals(textPos.val)) {
084            text = TextLabel.create(env, PaintColors.AREA_TEXT.get(), true);
085        }
086
087        Float extent = c.get(FILL_EXTENT, null, float.class);
088        Float extentThreshold = c.get(FILL_EXTENT_THRESHOLD, null, float.class);
089
090        if (color != null)
091            return new AreaElement(c, color, fillImage, extent, extentThreshold, text);
092        else
093            return null;
094    }
095
096    @Override
097    public void paintPrimitive(OsmPrimitive osm, MapPaintSettings paintSettings, StyledMapRenderer painter,
098            boolean selected, boolean outermember, boolean member) {
099        Color myColor = color;
100        if (osm instanceof Way) {
101            if (color != null) {
102                if (selected) {
103                    myColor = paintSettings.getSelectedColor(color.getAlpha());
104                } else if (outermember) {
105                    myColor = paintSettings.getRelationSelectedColor(color.getAlpha());
106                }
107            }
108            painter.drawArea((Way) osm, myColor, fillImage, extent, extentThreshold, painter.isInactiveMode() || osm.isDisabled(), text);
109        } else if (osm instanceof Relation) {
110            if (color != null && (selected || outermember)) {
111                myColor = paintSettings.getRelationSelectedColor(color.getAlpha());
112            }
113            painter.drawArea((Relation) osm, myColor, fillImage, extent, extentThreshold, painter.isInactiveMode() || osm.isDisabled(), text);
114        }
115    }
116
117    @Override
118    public boolean equals(Object obj) {
119        if (this == obj) return true;
120        if (obj == null || getClass() != obj.getClass()) return false;
121        if (!super.equals(obj)) return false;
122        AreaElement that = (AreaElement) obj;
123        return Objects.equals(color, that.color) &&
124                Objects.equals(fillImage, that.fillImage) &&
125                Objects.equals(text, that.text) &&
126                Objects.equals(extent, that.extent) &&
127                Objects.equals(extentThreshold, that.extentThreshold);
128    }
129
130    @Override
131    public int hashCode() {
132        return Objects.hash(super.hashCode(), color, fillImage, text, extent, extentThreshold);
133    }
134
135    @Override
136    public String toString() {
137        return "AreaElemStyle{" + super.toString() + "color=" + Utils.toString(color) +
138                " fillImage=[" + fillImage + "]}";
139    }
140}