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.JLabel;
011import javax.swing.SwingUtilities;
012
013import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
014import org.openstreetmap.josm.tools.OpenBrowser;
015import org.openstreetmap.josm.tools.Utils;
016
017/**
018 * Label that contains a clickable link.
019 * @since 6340
020 */
021public class UrlLabel extends JLabel implements MouseListener {
022
023    private String url = "";
024    private String description = "";
025
026    /**
027     * Constructs a new empty {@code UrlLabel}.
028     */
029    public UrlLabel() {
030        addMouseListener(this);
031        setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
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 fontPlus The font increase in 1/72 of an inch units.
065     */
066    public UrlLabel(String url, String description, int fontPlus) {
067        this();
068        setUrl(url);
069        setDescription(description);
070        if (fontPlus != 0) {
071            setFont(getFont().deriveFont(0, (float) getFont().getSize()+fontPlus));
072        }
073        refresh();
074    }
075
076    protected final void refresh() {
077        if (url != null && !url.isEmpty()) {
078            setText("<html><a href=\""+url+"\">"+description+"</a></html>");
079            setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
080            setToolTipText(String.format("<html>%s<br/>%s</html>", url, tr("Right click = copy to clipboard")));
081        } else {
082            setText("<html>" + description + "</html>");
083            setCursor(null);
084            setToolTipText(null);
085        }
086    }
087
088    /**
089     * Sets the URL to be visited if the user clicks on this URL label.
090     * If null or empty, the label turns into a normal label without hyperlink.
091     *
092     * @param url the url. Can be null.
093     */
094    public final void setUrl(String url) {
095        this.url = url;
096        refresh();
097    }
098
099    /**
100     * Sets the text part of the URL label. Defaults to the empty string if description is null.
101     *
102     * @param description the description
103     */
104    public final void setDescription(String description) {
105        setDescription(description, true);
106    }
107
108    /**
109     * Sets the text part of the URL label. Defaults to the empty string if description is null.
110     *
111     * @param description the description
112     * @param escapeReservedCharacters if {@code true}, HTML reserved characters will be escaped
113     * @since 13853
114     */
115    public final void setDescription(String description, boolean escapeReservedCharacters) {
116        this.description = description == null ? "" : description;
117        if (escapeReservedCharacters) {
118            this.description = Utils.escapeReservedCharactersHTML(this.description);
119        }
120        refresh();
121    }
122
123    @Override
124    public void mouseClicked(MouseEvent e) {
125        if (url != null && !url.isEmpty()) {
126            if (SwingUtilities.isLeftMouseButton(e)) {
127                OpenBrowser.displayUrl(url);
128            } else if (SwingUtilities.isRightMouseButton(e)) {
129                ClipboardUtils.copyString(url);
130            }
131        }
132    }
133
134    @Override
135    public void mousePressed(MouseEvent e) {
136        // Ignored
137    }
138
139    @Override
140    public void mouseEntered(MouseEvent e) {
141        // Ignored
142    }
143
144    @Override
145    public void mouseExited(MouseEvent e) {
146        // Ignored
147    }
148
149    @Override
150    public void mouseReleased(MouseEvent e) {
151        // Ignored
152    }
153}