001 // License: GPL. Copyright 2007 by Immanuel Scholz and others
002 package org.openstreetmap.josm.gui;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.awt.Component;
007 import java.awt.GridBagLayout;
008 import java.awt.HeadlessException;
009
010 import javax.swing.JCheckBox;
011 import javax.swing.JLabel;
012 import javax.swing.JOptionPane;
013 import javax.swing.JPanel;
014
015 import org.openstreetmap.josm.Main;
016 import org.openstreetmap.josm.tools.GBC;
017
018 /**
019 * ConditionalOptionPaneUtil provides static utility methods for displaying modal message dialogs
020 * which can be enabled/disabled by the user.
021 *
022 * They wrap the methods provided by {@link JOptionPane}. Within JOSM you should use these
023 * methods rather than the bare methods from {@link JOptionPane} because the methods provided
024 * by ConditionalOptionPaneUtil ensure that a dialog window is always on top and isn't hidden by one of the
025 * JOSM windows for detached dialogs, relation editors, history browser and the like.
026 *
027 */
028 public class ConditionalOptionPaneUtil {
029 static public final int DIALOG_DISABLED_OPTION = Integer.MIN_VALUE;
030
031 /**
032 * this is a static utility class only
033 */
034 private ConditionalOptionPaneUtil() {}
035
036 /**
037 * Replies the preference value for the preference key "message." + <code>prefKey</code>.
038 * The default value if the preference key is missing is true.
039 *
040 * @param the preference key
041 * @return prefKey the preference value for the preference key "message." + <code>prefKey</code>
042 */
043 public static boolean getDialogShowingEnabled(String prefKey) {
044 return Main.pref.getBoolean("message."+prefKey, true);
045 }
046
047 /**
048 * sets the value for the preference key "message." + <code>prefKey</code>.
049 *
050 * @param prefKey the key
051 * @param enabled the value
052 */
053 public static void setDialogShowingEnabled(String prefKey, boolean enabled) {
054 Main.pref.put("message."+prefKey, enabled);
055 }
056
057 /**
058 * Returns the preference value for the preference key "message." + <code>prefKey</code> + ".value".
059 * The default value if the preference key is missing is -1.
060 *
061 * @param the preference key
062 * @return prefKey the preference value for the preference key "message." + <code>prefKey</code> + ".value"
063 */
064 public static Integer getDialogReturnValue(String prefKey) {
065 return Main.pref.getInteger("message."+prefKey+".value", -1);
066 }
067
068 /**
069 * sets the value for the preference key "message." + <code>prefKey</code> + ".value".
070 *
071 * @param prefKey the key
072 * @param value the value
073 */
074 public static void setDialogReturnValue(String prefKey, Integer value) {
075 Main.pref.putInteger("message."+prefKey+".value", value);
076 }
077
078 /**
079 * Displays an confirmation dialog with some option buttons given by <code>optionType</code>.
080 * It is always on top even if there are other open windows like detached dialogs,
081 * relation editors, history browsers and the like.
082 *
083 * Set <code>optionType</code> to {@link JOptionPane#YES_NO_OPTION} for a dialog with a YES and
084 * a NO button.
085
086 * Set <code>optionType</code> to {@link JOptionPane#YES_NO_CANCEL_OPTION} for a dialog with a YES,
087 * a NO and a CANCEL button
088 *
089 * Returns one of the constants JOptionPane.YES_OPTION, JOptionPane.NO_OPTION,
090 * JOptionPane.CANCEL_OPTION or JOptionPane.CLOSED_OPTION depending on the action chosen by
091 * the user.
092 *
093 * @param preferenceKey the preference key
094 * @param parent the parent component
095 * @param message the message
096 * @param title the title
097 * @param optionType the option type
098 * @param messageType the message type
099 * @param options a list of options
100 * @param defaultOption the default option
101 *
102 * @return the option selected by user. {@link JOptionPane#CLOSED_OPTION} if the dialog was closed.
103 */
104 static public int showOptionDialog(String preferenceKey, Component parent, Object message, String title, int optionType, int messageType, Object [] options, Object defaultOption) throws HeadlessException {
105 int ret = getDialogReturnValue(preferenceKey);
106 if (!getDialogShowingEnabled(preferenceKey) && ((ret == JOptionPane.YES_OPTION) || (ret == JOptionPane.NO_OPTION)))
107 return ret;
108 MessagePanel pnl = new MessagePanel(false, message);
109 ret = JOptionPane.showOptionDialog(parent, pnl, title, optionType, messageType, null, options, defaultOption);
110
111 if (((ret == JOptionPane.YES_OPTION) || (ret == JOptionPane.NO_OPTION)) && !pnl.getDialogShowingEnabled()) {
112 setDialogShowingEnabled(preferenceKey, false);
113 setDialogReturnValue(preferenceKey, ret);
114 }
115 return ret;
116 }
117
118 /**
119 * Displays a confirmation dialog with some option buttons given by <code>optionType</code>.
120 * It is always on top even if there are other open windows like detached dialogs,
121 * relation editors, history browsers and the like.
122 *
123 * Set <code>optionType</code> to {@link JOptionPane#YES_NO_OPTION} for a dialog with a YES and
124 * a NO button.
125
126 * Set <code>optionType</code> to {@link JOptionPane#YES_NO_CANCEL_OPTION} for a dialog with a YES,
127 * a NO and a CANCEL button
128 *
129 * Replies true, if the selected option is equal to <code>trueOption</code>, otherwise false.
130 * Replies true, if the dialog is not displayed because the respective preference option
131 * <code>preferenceKey</code> is set to false and the user has previously chosen
132 * <code>trueOption</code>.
133 *
134 * @param preferenceKey the preference key
135 * @param parent the parent component
136 * @param message the message
137 * @param title the title
138 * @param optionType the option type
139 * @param messageType the message type
140 * @param trueOption if this option is selected the method replies true
141 *
142 *
143 * @return true, if the selected option is equal to <code>trueOption</code>, otherwise false.
144 *
145 * @see JOptionPane#INFORMATION_MESSAGE
146 * @see JOptionPane#WARNING_MESSAGE
147 * @see JOptionPane#ERROR_MESSAGE
148 */
149 static public boolean showConfirmationDialog(String preferenceKey, Component parent, Object message, String title, int optionType, int messageType, int trueOption) throws HeadlessException {
150 int ret = getDialogReturnValue(preferenceKey);
151 if (!getDialogShowingEnabled(preferenceKey) && ((ret == JOptionPane.YES_OPTION) || (ret == JOptionPane.NO_OPTION)))
152 return ret == trueOption;
153 MessagePanel pnl = new MessagePanel(false, message);
154 ret = JOptionPane.showConfirmDialog(parent, pnl, title, optionType, messageType);
155 if (((ret == JOptionPane.YES_OPTION) || (ret == JOptionPane.NO_OPTION)) && !pnl.getDialogShowingEnabled()) {
156 setDialogShowingEnabled(preferenceKey, false);
157 setDialogReturnValue(preferenceKey, ret);
158 }
159 return ret == trueOption;
160 }
161
162 /**
163 * Displays an message in modal dialog with an OK button. Makes sure the dialog
164 * is always on top even if there are other open windows like detached dialogs,
165 * relation editors, history browsers and the like.
166 *
167 * If there is a preference with key <code>preferenceKey</code> and value <code>false</code>
168 * the dialog is not show.
169 *
170 * @param preferenceKey the preference key
171 * @param parent the parent component
172 * @param message the message
173 * @param title the title
174 * @param messageType the message type
175 *
176 * @see JOptionPane#INFORMATION_MESSAGE
177 * @see JOptionPane#WARNING_MESSAGE
178 * @see JOptionPane#ERROR_MESSAGE
179 */
180 static public void showMessageDialog(String preferenceKey, Component parent, Object message, String title,int messageType) {
181 if (!getDialogShowingEnabled(preferenceKey))
182 return;
183 MessagePanel pnl = new MessagePanel(false, message);
184 JOptionPane.showMessageDialog(parent, pnl, title, messageType);
185 if(!pnl.getDialogShowingEnabled()) {
186 setDialogShowingEnabled(preferenceKey, false);
187 }
188 }
189
190 /**
191 * This is a message panel used in dialogs which can be enabled/disabled with a preference
192 * setting.
193 * In addition to the normal message any {@link JOptionPane} would display it includes
194 * a checkbox for enabling/disabling this particular dialog.
195 *
196 */
197 private static class MessagePanel extends JPanel {
198 JCheckBox cbShowDialog;
199
200 public MessagePanel(boolean donotshow, Object message) {
201 cbShowDialog = new JCheckBox(tr("Do not show again (remembers choice)"));
202 cbShowDialog.setSelected(donotshow);
203 setLayout(new GridBagLayout());
204
205 if (message instanceof Component) {
206 add((Component)message, GBC.eop());
207 } else {
208 add(new JLabel(message.toString()),GBC.eop());
209 }
210 add(cbShowDialog, GBC.eol());
211 }
212
213 public boolean getDialogShowingEnabled() {
214 return !cbShowDialog.isSelected();
215 }
216 }
217 }