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