001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui;
003
004import java.awt.Color;
005import java.awt.Component;
006
007import javax.swing.Icon;
008import javax.swing.JEditorPane;
009import javax.swing.JOptionPane;
010import javax.swing.UIManager;
011
012import org.openstreetmap.josm.Main;
013import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
014
015/**
016 * A Notification Message similar to a popup window, but without disrupting the
017 * user's workflow.
018 *
019 * Non-modal info panel that vanishes after a certain time.
020 *
021 * This class only holds the data for a notification, {@link NotificationManager}
022 * is responsible for building the message panel and displaying it on screen.
023 *
024 * example:
025 * <pre>
026 *      Notification note = new Notification("Hi there!");
027 *      note.setIcon(JOptionPane.INFORMATION_MESSAGE); // optional
028 *      note.setDuration(Notification.TIME_SHORT); // optional
029 *      note.show();
030 * </pre>
031 */
032public class Notification {
033
034    /**
035     * Default width of a notification
036     */
037    public static final int DEFAULT_CONTENT_WIDTH = 350;
038
039    // some standard duration values (in milliseconds)
040
041    /**
042     * Very short and very easy to grasp message (3 s).
043     * E.g. "Please select at least one node".
044     */
045    public static final int TIME_SHORT = Main.pref.getInteger("notification-time-short-ms", 3000);
046
047    /**
048     * Short message of one or two lines (5 s).
049     */
050    public static final int TIME_DEFAULT = Main.pref.getInteger("notification-time-default-ms", 5000);
051
052    /**
053     * Somewhat longer message (10 s).
054     */
055    public static final int TIME_LONG = Main.pref.getInteger("notification-time-long-ms", 10_000);
056
057    /**
058     * Long text.
059     * (Make sure is still sensible to show as a notification)
060     */
061    public static final int TIME_VERY_LONG = Main.pref.getInteger("notification-time-very_long-ms", 20_000);
062
063    private Component content;
064    private int duration = Notification.TIME_DEFAULT;
065    private Icon icon;
066    private String helpTopic;
067
068    /**
069     * Constructs a new {@code Notification} without content.
070     */
071    public Notification() {
072        // nothing to do.
073    }
074
075    /**
076     * Constructs a new {@code Notification} with the given textual content.
077     * @param msg The text to display
078     */
079    public Notification(String msg) {
080        this();
081        setContent(msg);
082    }
083
084    /**
085     * Set the content of the message.
086     *
087     * @param content any Component to be shown
088     *
089     * @return the current Object, for convenience
090     * @see #setContent(java.lang.String)
091     */
092    public Notification setContent(Component content) {
093        this.content = content;
094        return this;
095    }
096
097    /**
098     * Set the notification text. (Convenience method)
099     *
100     * @param msg the message String. Will be wrapped in &lt;html&gt;, so
101     * you can use &lt;br&gt; and other markup directly.
102     *
103     * @return the current Object, for convenience
104     * @see #Notification(java.lang.String)
105     */
106    public Notification setContent(String msg) {
107        JMultilineLabel lbl = new JMultilineLabel(msg);
108        lbl.setMaxWidth(DEFAULT_CONTENT_WIDTH);
109        lbl.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
110        lbl.setForeground(Color.BLACK);
111        content = lbl;
112        return this;
113    }
114
115    /**
116     * Set the time after which the message is hidden.
117     *
118     * @param duration the time (in milliseconds)
119     * Preset values {@link #TIME_SHORT}, {@link #TIME_DEFAULT}, {@link #TIME_LONG}
120     * and {@link #TIME_VERY_LONG} can be used.
121     * @return the current Object, for convenience
122     */
123    public Notification setDuration(int duration) {
124        this.duration = duration;
125        return this;
126    }
127
128    /**
129     * Set an icon to display on the left part of the message window.
130     *
131     * @param icon the icon (null means no icon is displayed)
132     * @return the current Object, for convenience
133     */
134    public Notification setIcon(Icon icon) {
135        this.icon = icon;
136        return this;
137    }
138
139    /**
140     * Set an icon to display on the left part of the message window by
141     * choosing from the default JOptionPane icons.
142     *
143     * @param messageType one of the following: JOptionPane.ERROR_MESSAGE,
144     * JOptionPane.INFORMATION_MESSAGE, JOptionPane.WARNING_MESSAGE,
145     * JOptionPane.QUESTION_MESSAGE, JOptionPane.PLAIN_MESSAGE
146     * @return the current Object, for convenience
147     */
148    public Notification setIcon(int messageType) {
149        switch (messageType) {
150            case JOptionPane.ERROR_MESSAGE:
151                return setIcon(UIManager.getIcon("OptionPane.errorIcon"));
152            case JOptionPane.INFORMATION_MESSAGE:
153                return setIcon(UIManager.getIcon("OptionPane.informationIcon"));
154            case JOptionPane.WARNING_MESSAGE:
155                return setIcon(UIManager.getIcon("OptionPane.warningIcon"));
156            case JOptionPane.QUESTION_MESSAGE:
157                return setIcon(UIManager.getIcon("OptionPane.questionIcon"));
158            case JOptionPane.PLAIN_MESSAGE:
159                return setIcon(null);
160            default:
161                throw new IllegalArgumentException("Unknown message type!");
162        }
163    }
164
165    /**
166     * Display a help button at the bottom of the notification window.
167     * @param helpTopic the help topic
168     * @return the current Object, for convenience
169     */
170    public Notification setHelpTopic(String helpTopic) {
171        this.helpTopic = helpTopic;
172        return this;
173    }
174
175    /**
176     * Gets the content component to use.
177     * @return The content
178     */
179    public Component getContent() {
180        return content;
181    }
182
183    /**
184     * Gets the time the notification should be displayed
185     * @return The time to display the notification
186     */
187    public int getDuration() {
188        return duration;
189    }
190
191    /**
192     * Gets the icon that should be displayed next to the notification
193     * @return The icon to display
194     */
195    public Icon getIcon() {
196        return icon;
197    }
198
199    /**
200     * Gets the help topic for this notification
201     * @return The help topic
202     */
203    public String getHelpTopic() {
204        return helpTopic;
205    }
206
207    /**
208     * Display the notification.
209     */
210    public void show() {
211        NotificationManager.getInstance().showNotification(this);
212    }
213}