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}