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 }