001// License: GPL. For details, see Readme.txt file.
002package org.openstreetmap.gui.jmapviewer;
003
004import static org.openstreetmap.gui.jmapviewer.FeatureAdapter.tr;
005
006import java.awt.Color;
007import java.awt.Font;
008import java.awt.Graphics;
009import java.awt.Image;
010import java.awt.Point;
011import java.awt.Rectangle;
012import java.awt.font.TextAttribute;
013import java.awt.geom.Rectangle2D;
014import java.awt.image.ImageObserver;
015import java.util.HashMap;
016
017import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
018import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
019
020public class AttributionSupport {
021
022    private Attributed source;
023
024    private Image attrImage;
025    private String attrTermsText;
026    private String attrTermsUrl;
027    public static final Font ATTR_FONT = new Font("Arial", Font.PLAIN, 10);
028    public static final Font ATTR_LINK_FONT;
029
030    protected Rectangle attrTextBounds;
031    protected Rectangle attrToUBounds;
032    protected Rectangle attrImageBounds;
033
034    static {
035        HashMap<TextAttribute, Integer> aUnderline = new HashMap<>();
036        aUnderline.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
037        ATTR_LINK_FONT = ATTR_FONT.deriveFont(aUnderline);
038    }
039
040    public void initialize(Attributed source) {
041        this.source = source;
042        boolean requireAttr = source.requiresAttribution();
043        if (requireAttr) {
044            attrImage = source.getAttributionImage();
045            attrTermsText = source.getTermsOfUseText();
046            attrTermsUrl = source.getTermsOfUseURL();
047            if (attrTermsUrl != null && attrTermsText == null) {
048                attrTermsText = tr("Background Terms of Use");
049            }
050        } else {
051            attrImage = null;
052            attrTermsUrl = null;
053        }
054    }
055
056    public void paintAttribution(Graphics g, int width, int height, ICoordinate topLeft, ICoordinate bottomRight,
057            int zoom, ImageObserver observer) {
058        if (source == null || !source.requiresAttribution()) {
059            attrToUBounds = null;
060            attrImageBounds = null;
061            attrTextBounds = null;
062            return;
063        }
064
065        // Draw attribution
066        Font font = g.getFont();
067        g.setFont(ATTR_LINK_FONT);
068
069        // Draw terms of use text
070        int termsTextHeight = 0;
071        int termsTextY = height;
072
073        if (attrTermsText != null) {
074            Rectangle2D termsStringBounds = g.getFontMetrics().getStringBounds(attrTermsText, g);
075            int textRealHeight = (int) termsStringBounds.getHeight();
076            termsTextHeight = textRealHeight - 5;
077            int termsTextWidth = (int) termsStringBounds.getWidth();
078            termsTextY = height - termsTextHeight;
079            int x = 2;
080            int y = height - termsTextHeight;
081            attrToUBounds = new Rectangle(x, y-termsTextHeight, termsTextWidth, textRealHeight);
082            g.setColor(Color.black);
083            g.drawString(attrTermsText, x + 1, y + 1);
084            g.setColor(Color.white);
085            g.drawString(attrTermsText, x, y);
086        } else {
087            attrToUBounds = null;
088        }
089
090        // Draw attribution logo
091        if (attrImage != null) {
092            int x = 2;
093            int imgWidth = attrImage.getWidth(observer);
094            int imgHeight = attrImage.getHeight(observer);
095            int y = termsTextY - imgHeight - termsTextHeight - 5;
096            attrImageBounds = new Rectangle(x, y, imgWidth, imgHeight);
097            g.drawImage(attrImage, x, y, null);
098        } else {
099            attrImageBounds = null;
100        }
101
102        g.setFont(ATTR_FONT);
103        String attributionText = source.getAttributionText(zoom, topLeft, bottomRight);
104        if (attributionText == null) {
105            // In case attribution text has been forgotte, display URL
106            attributionText = source.getAttributionLinkURL();
107        }
108        if (attributionText != null) {
109            Rectangle2D stringBounds = g.getFontMetrics().getStringBounds(attributionText, g);
110            int textHeight = (int) stringBounds.getHeight() - 5;
111            int x = width - (int) stringBounds.getWidth();
112            int y = height - textHeight;
113            g.setColor(Color.black);
114            g.drawString(attributionText, x + 1, y + 1);
115            g.setColor(Color.white);
116            g.drawString(attributionText, x, y);
117            attrTextBounds = new Rectangle(x, y-textHeight, (int) stringBounds.getWidth(), (int) stringBounds.getHeight());
118        } else {
119            attrTextBounds = null;
120        }
121
122        g.setFont(font);
123    }
124
125    public boolean handleAttributionCursor(Point p) {
126        if (attrTextBounds != null && attrTextBounds.contains(p)) {
127            return true;
128        } else if (attrImageBounds != null && attrImageBounds.contains(p)) {
129            return true;
130        } else if (attrToUBounds != null && attrToUBounds.contains(p)) {
131            return true;
132        }
133        return false;
134    }
135
136    public boolean handleAttribution(Point p, boolean click) {
137        if (source == null || !source.requiresAttribution())
138            return false;
139
140        if (attrTextBounds != null && attrTextBounds.contains(p)) {
141            String attributionURL = source.getAttributionLinkURL();
142            if (attributionURL != null) {
143                if (click) {
144                    FeatureAdapter.openLink(attributionURL);
145                }
146                return true;
147            }
148        } else if (attrImageBounds != null && attrImageBounds.contains(p)) {
149            String attributionImageURL = source.getAttributionImageURL();
150            if (attributionImageURL != null) {
151                if (click) {
152                    FeatureAdapter.openLink(source.getAttributionImageURL());
153                }
154                return true;
155            }
156        } else if (attrToUBounds != null && attrToUBounds.contains(p)) {
157            String termsOfUseURL = source.getTermsOfUseURL();
158            if (termsOfUseURL != null) {
159                if (click) {
160                    FeatureAdapter.openLink(termsOfUseURL);
161                }
162                return true;
163            }
164        }
165        return false;
166    }
167
168}
169