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