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            Rectangle2D stringBounds = g.getFontMetrics().getStringBounds(attributionText, g);
106            int textHeight = (int) stringBounds.getHeight() - 5;
107            int x = width - (int) stringBounds.getWidth();
108            int y = height - textHeight;
109            g.setColor(Color.black);
110            g.drawString(attributionText, x + 1, y + 1);
111            g.setColor(Color.white);
112            g.drawString(attributionText, x, y);
113            attrTextBounds = new Rectangle(x, y-textHeight, (int) stringBounds.getWidth(), (int) stringBounds.getHeight());
114        } else {
115            attrTextBounds = null;
116        }
117
118        g.setFont(font);
119    }
120
121    public boolean handleAttributionCursor(Point p) {
122        if (attrTextBounds != null && attrTextBounds.contains(p)) {
123            return true;
124        } else if (attrImageBounds != null && attrImageBounds.contains(p)) {
125            return true;
126        } else if (attrToUBounds != null && attrToUBounds.contains(p)) {
127            return true;
128        }
129        return false;
130    }
131
132    public boolean handleAttribution(Point p, boolean click) {
133        if (source == null || !source.requiresAttribution())
134            return false;
135
136        if (attrTextBounds != null && attrTextBounds.contains(p)) {
137            String attributionURL = source.getAttributionLinkURL();
138            if (attributionURL != null) {
139                if (click) {
140                    FeatureAdapter.openLink(attributionURL);
141                }
142                return true;
143            }
144        } else if (attrImageBounds != null && attrImageBounds.contains(p)) {
145            String attributionImageURL = source.getAttributionImageURL();
146            if (attributionImageURL != null) {
147                if (click) {
148                    FeatureAdapter.openLink(source.getAttributionImageURL());
149                }
150                return true;
151            }
152        } else if (attrToUBounds != null && attrToUBounds.contains(p)) {
153            String termsOfUseURL = source.getTermsOfUseURL();
154            if (termsOfUseURL != null) {
155                if (click) {
156                    FeatureAdapter.openLink(termsOfUseURL);
157                }
158                return true;
159            }
160        }
161        return false;
162    }
163
164}
165