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