001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.widgets; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Cursor; 007import java.awt.event.MouseEvent; 008import java.awt.event.MouseListener; 009 010import javax.swing.Icon; 011import javax.swing.JLabel; 012import javax.swing.SwingUtilities; 013 014import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 015import org.openstreetmap.josm.tools.OpenBrowser; 016import org.openstreetmap.josm.tools.Utils; 017 018/** 019 * Label that contains a clickable link. 020 * @since 6340 021 */ 022public class UrlLabel extends JLabel implements MouseListener { 023 024 private String url = ""; 025 private String description = ""; 026 027 /** 028 * Constructs a new empty {@code UrlLabel}. 029 */ 030 public UrlLabel() { 031 init("", "", 0); 032 } 033 034 /** 035 * Constructs a new {@code UrlLabel} for the given URL. 036 * @param url The URL to use, also used as description 037 */ 038 public UrlLabel(String url) { 039 this (url, url, 0); 040 } 041 042 /** 043 * Constructs a new {@code UrlLabel} for the given URL and font increase. 044 * @param url The URL to use, also used as description 045 * @param fontPlus The font increase in 1/72 of an inch units. 046 */ 047 public UrlLabel(String url, int fontPlus) { 048 this (url, url, fontPlus); 049 } 050 051 /** 052 * Constructs a new {@code UrlLabel} for the given URL and description. 053 * @param url The URL to use 054 * @param description The description to display 055 */ 056 public UrlLabel(String url, String description) { 057 this (url, description, 0); 058 } 059 060 /** 061 * Constructs a new {@code UrlLabel} for the given URL, description and font increase. 062 * @param url The URL to use 063 * @param description The description to display 064 * @param image The image to be displayed by the label instead of text 065 * @since 14822 066 */ 067 public UrlLabel(String url, String description, Icon image) { 068 super(image); 069 init(url, description, 0); 070 } 071 072 /** 073 * Constructs a new {@code UrlLabel} for the given URL, description and font increase. 074 * @param url The URL to use 075 * @param description The description to display 076 * @param fontPlus The font increase in 1/72 of an inch units. 077 */ 078 public UrlLabel(String url, String description, int fontPlus) { 079 init(url, description, fontPlus); 080 } 081 082 private void init(String url, String description, int fontPlus) { 083 addMouseListener(this); 084 setUrl(url); 085 setDescription(description); 086 if (fontPlus != 0) { 087 setFont(getFont().deriveFont(0, (float) getFont().getSize()+fontPlus)); 088 } 089 refresh(); 090 } 091 092 protected final void refresh() { 093 if (url != null && !url.isEmpty()) { 094 refresh("<html><a href=\""+url+"\">"+description+"</a></html>", 095 Cursor.getPredefinedCursor(Cursor.HAND_CURSOR), 096 String.format("<html>%s<br/>%s</html>", url, tr("Right click = copy to clipboard"))); 097 } else { 098 refresh("<html>" + description + "</html>", null, null); 099 } 100 } 101 102 private void refresh(String text, Cursor cursor, String tooltip) { 103 boolean hasImage = getIcon() != null; 104 if (!hasImage) { 105 setText(text); 106 } 107 setCursor(cursor); 108 setToolTipText(tooltip); 109 } 110 111 /** 112 * Sets the URL to be visited if the user clicks on this URL label. 113 * If null or empty, the label turns into a normal label without hyperlink. 114 * 115 * @param url the url. Can be null. 116 */ 117 public final void setUrl(String url) { 118 this.url = url; 119 refresh(); 120 } 121 122 /** 123 * Sets the text part of the URL label. Defaults to the empty string if description is null. 124 * 125 * @param description the description 126 */ 127 public final void setDescription(String description) { 128 setDescription(description, true); 129 } 130 131 /** 132 * Sets the text part of the URL label. Defaults to the empty string if description is null. 133 * 134 * @param description the description 135 * @param escapeReservedCharacters if {@code true}, HTML reserved characters will be escaped 136 * @since 13853 137 */ 138 public final void setDescription(String description, boolean escapeReservedCharacters) { 139 this.description = description == null ? "" : description; 140 if (escapeReservedCharacters) { 141 this.description = Utils.escapeReservedCharactersHTML(this.description); 142 } 143 refresh(); 144 } 145 146 @Override 147 public void mouseClicked(MouseEvent e) { 148 if (url != null && !url.isEmpty()) { 149 if (SwingUtilities.isLeftMouseButton(e)) { 150 OpenBrowser.displayUrl(url); 151 } else if (SwingUtilities.isRightMouseButton(e)) { 152 ClipboardUtils.copyString(url); 153 } 154 } 155 } 156 157 @Override 158 public void mousePressed(MouseEvent e) { 159 // Ignored 160 } 161 162 @Override 163 public void mouseEntered(MouseEvent e) { 164 // Ignored 165 } 166 167 @Override 168 public void mouseExited(MouseEvent e) { 169 // Ignored 170 } 171 172 @Override 173 public void mouseReleased(MouseEvent e) { 174 // Ignored 175 } 176}