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