annotate java/src/uk/ac/qmul/eecs/ccmi/gui/SpeechOptionPane.java @ 1:e3935c01cde2 tip

moved license of PdPersistenceManager to the beginning of the file
author Fiore Martin <f.martin@qmul.ac.uk>
date Tue, 08 Jul 2014 19:52:03 +0100
parents 78b7fc5391a2
children
rev   line source
f@0 1 /*
f@0 2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
f@0 3
f@0 4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
f@0 5
f@0 6 This program is free software: you can redistribute it and/or modify
f@0 7 it under the terms of the GNU General Public License as published by
f@0 8 the Free Software Foundation, either version 3 of the License, or
f@0 9 (at your option) any later version.
f@0 10
f@0 11 This program is distributed in the hope that it will be useful,
f@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@0 14 GNU General Public License for more details.
f@0 15
f@0 16 You should have received a copy of the GNU General Public License
f@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@0 18 */
f@0 19
f@0 20 package uk.ac.qmul.eecs.ccmi.gui;
f@0 21
f@0 22 import java.awt.Color;
f@0 23 import java.awt.Component;
f@0 24 import java.awt.Frame;
f@0 25 import java.awt.GridLayout;
f@0 26 import java.awt.event.ActionEvent;
f@0 27 import java.awt.event.ActionListener;
f@0 28 import java.awt.event.InputEvent;
f@0 29 import java.awt.event.KeyEvent;
f@0 30 import java.awt.event.WindowAdapter;
f@0 31 import java.awt.event.WindowEvent;
f@0 32 import java.text.MessageFormat;
f@0 33 import java.util.LinkedHashSet;
f@0 34 import java.util.List;
f@0 35 import java.util.ResourceBundle;
f@0 36 import java.util.Set;
f@0 37
f@0 38 import javax.swing.AbstractAction;
f@0 39 import javax.swing.JButton;
f@0 40 import javax.swing.JCheckBox;
f@0 41 import javax.swing.JComponent;
f@0 42 import javax.swing.JDialog;
f@0 43 import javax.swing.JFormattedTextField;
f@0 44 import javax.swing.JLabel;
f@0 45 import javax.swing.JOptionPane;
f@0 46 import javax.swing.JPanel;
f@0 47 import javax.swing.JProgressBar;
f@0 48 import javax.swing.JScrollPane;
f@0 49 import javax.swing.JSpinner;
f@0 50 import javax.swing.JTextArea;
f@0 51 import javax.swing.JTextField;
f@0 52 import javax.swing.KeyStroke;
f@0 53 import javax.swing.SwingWorker;
f@0 54 import javax.swing.event.ChangeEvent;
f@0 55 import javax.swing.event.ChangeListener;
f@0 56 import javax.swing.text.JTextComponent;
f@0 57
f@0 58 import uk.ac.qmul.eecs.ccmi.sound.SoundEvent;
f@0 59 import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
f@0 60 import uk.ac.qmul.eecs.ccmi.speech.Narrator;
f@0 61 import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory;
f@0 62 import uk.ac.qmul.eecs.ccmi.speech.SpeechUtilities;
f@0 63
f@0 64 /**
f@0 65 *
f@0 66 * An option panel made out of an {@code Object} being displayed and to buttons: one for accepting and another one for
f@0 67 * cancelling the option.
f@0 68 * Furthermore, this class provides one-line calls to display accessible dialog boxes. Input by the user as well
f@0 69 * as focused components are spoken out through text to speech synthesis performed by a {@link Narrator} instance.
f@0 70 */
f@0 71 public class SpeechOptionPane {
f@0 72
f@0 73 /**
f@0 74 * Construct a new {@code SpeechOptionPane} with no title. The title is displayed at the top of the dialog
f@0 75 * that is displayed after a call to {@code showDialog}
f@0 76 */
f@0 77 public SpeechOptionPane(){
f@0 78 this("");
f@0 79 }
f@0 80
f@0 81 /**
f@0 82 * Construct a new {@code SpeechOptionPane} with no title. The title is displayed at the top of the dialog
f@0 83 * that is displayed after a call to {@code showDialog}
f@0 84 *
f@0 85 * @param title the String to be displayed
f@0 86 */
f@0 87 public SpeechOptionPane(String title){
f@0 88 this.title = title;
f@0 89 okButton = new JButton("OK");
f@0 90 cancelButton = new JButton("Cancel");
f@0 91 }
f@0 92
f@0 93 /**
f@0 94 * Pops the a dialog holding this SpeechOptionPane
f@0 95 *
f@0 96 * @param parent the parent component of the dialog
f@0 97 * @param message the {@code Object} to display
f@0 98 * @return an integer indicating the option selected by the user
f@0 99 */
f@0 100 @SuppressWarnings("serial")
f@0 101 public int showDialog(Component parent,final Object message){
f@0 102 optPane = new JOptionPane();
f@0 103 optPane.setMessage(message);
f@0 104 /* Enter will entail a unique action, regardless the component that's focused */
f@0 105 optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "closeDialog");
f@0 106 optPane.getActionMap().put("closeDialog", new AbstractAction(){
f@0 107 @Override
f@0 108 public void actionPerformed(ActionEvent evt) {
f@0 109 okButton.doClick();
f@0 110 }
f@0 111 });
f@0 112 optPane.setMessageType(JOptionPane.PLAIN_MESSAGE);
f@0 113 Object[] options = {
f@0 114 okButton,
f@0 115 cancelButton
f@0 116 };
f@0 117 optPane.setOptions(options);
f@0 118 /* ctrl key will hush the TTS */
f@0 119 optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up");
f@0 120 optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction());
f@0 121 final JDialog dialog = optPane.createDialog(parent, title);
f@0 122 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
f@0 123 SpeechUtilities.changeTabListener(optPane,dialog);
f@0 124 /* when either button is pressed, dialog is disposed and the button itself becomes the optPane.value */
f@0 125 ActionListener buttonListener = new ActionListener(){
f@0 126 @Override
f@0 127 public void actionPerformed(ActionEvent evt) {
f@0 128 onClose(dialog,(JButton)evt.getSource());
f@0 129 }
f@0 130 };
f@0 131 okButton.addActionListener(buttonListener);
f@0 132 cancelButton.addActionListener(buttonListener);
f@0 133
f@0 134 SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
f@0 135 dialog.setVisible(true);
f@0 136 SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
f@0 137 if(okButton.equals(optPane.getValue())){
f@0 138 return OK_OPTION;
f@0 139 }else{
f@0 140 return CANCEL_OPTION;
f@0 141 }
f@0 142 }
f@0 143
f@0 144 /**
f@0 145 * Sets the string appearing at the top of the dialog where this option pane is displayed when {@code showDialog}
f@0 146 * is called.
f@0 147 * @param title the title of this option pane
f@0 148 */
f@0 149 public void setDialogTitle(String title){
f@0 150 this.title = title;
f@0 151 }
f@0 152
f@0 153 /**
f@0 154 * Returns the {@code JButton} that the user has to press (when the option pane is displayed after
f@0 155 * {@code showDialog} is called) in order to accept the option.
f@0 156 *
f@0 157 * @return a reference to the internal {@code JButton}
f@0 158 */
f@0 159 public JButton getOkButton(){
f@0 160 return okButton;
f@0 161 }
f@0 162
f@0 163 /**
f@0 164 * Returns the {@code JButton} that the user has to press (when the option pane is displayed after
f@0 165 * {@code showDialog} is called) in order to reject the option.
f@0 166 *
f@0 167 * @return a reference to the internal {@code JButton}
f@0 168 */
f@0 169 public JButton getCancelButton(){
f@0 170 return cancelButton;
f@0 171 }
f@0 172
f@0 173 /**
f@0 174 * This method is called just after the user presses either button of the dialog displayed
f@0 175 * after {@code showDialog} is called.
f@0 176 * It assign a value to the return value and it frees the dialog resources.
f@0 177 * It can be overwritten by subclasses but care should be taken of calling this class method via
f@0 178 * {@code super} in order to properly close the dialog.
f@0 179 *
f@0 180 * @param dialog the dialog displayed after {@code showDialog} is called.
f@0 181 * @param source the button that triggered the closing of {@code dialog}
f@0 182 */
f@0 183 protected void onClose(JDialog dialog, JButton source){
f@0 184 optPane.setValue(source);
f@0 185 dialog.dispose();
f@0 186 }
f@0 187
f@0 188 private String title;
f@0 189 private JOptionPane optPane;
f@0 190 private JButton okButton;
f@0 191 private JButton cancelButton;
f@0 192
f@0 193
f@0 194 /* -------- STATIC METHODS ----------- */
f@0 195
f@0 196 /**
f@0 197 * Shows a dialog with a text area requesting input for the user.
f@0 198 *
f@0 199 * @param parentComponent the parent {@code Component} for the dialog
f@0 200 * @param message a displayed in the dialog, such text is also uttered by the {@code Narrator}
f@0 201 * @param text the initial text the text area contains when the dialog is displayed
f@0 202 *
f@0 203 * @return the new text entered by the user
f@0 204 */
f@0 205 public static String showTextAreaDialog(Component parentComponent, String message, String text){
f@0 206 JTextArea textArea = new JTextArea(NOTES_TEXT_AREA_ROW_SIZE,NOTES_TEXT_AREA_COL_SIZE);
f@0 207 textArea.setText(text);
f@0 208 NarratorFactory.getInstance().speak(message);
f@0 209 return textComponentDialog(parentComponent, message, textArea);
f@0 210 }
f@0 211
f@0 212 /**
f@0 213 * Shows a dialog with a text field requesting input from the user
f@0 214 *
f@0 215 * @param parentComponent the parent {@code Component} for the dialog
f@0 216 * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
f@0 217 * @param initialSelectionValue the initial text the text field contains when the dialog is displayed
f@0 218 *
f@0 219 * @return the text entered by the user
f@0 220 */
f@0 221 public static String showInputDialog(Component parentComponent, String message, String initialSelectionValue){
f@0 222 final JTextField textField = new JTextField(initialSelectionValue);
f@0 223 textField.selectAll();
f@0 224 NarratorFactory.getInstance().speak(message);
f@0 225 return textComponentDialog(parentComponent, message, textField);
f@0 226 }
f@0 227
f@0 228 private static String textComponentDialog(Component parentComponent, String message, final JTextComponent textComponent){
f@0 229 Object componentToDisplay = textComponent;
f@0 230 if(textComponent instanceof JTextArea)
f@0 231 componentToDisplay = new JScrollPane(textComponent);
f@0 232
f@0 233 Object[] displayObjects = { new JLabel(message), componentToDisplay };
f@0 234 final JOptionPane optPane = new JOptionPane();
f@0 235 optPane.setMessage(displayObjects);
f@0 236 optPane.setMessageType(QUESTION_MESSAGE);
f@0 237 optPane.setOptionType(OK_CANCEL_OPTION);
f@0 238 /* ctrl key will hush the TTS */
f@0 239 optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up");
f@0 240 optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction());
f@0 241
f@0 242 final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.input"));
f@0 243 if(textComponent instanceof JTextArea)
f@0 244 dialog.setResizable(true);
f@0 245 dialog.addWindowFocusListener(new WindowAdapter(){
f@0 246 @Override
f@0 247 public void windowGainedFocus(WindowEvent e) {
f@0 248 textComponent.requestFocusInWindow();
f@0 249 }
f@0 250 });
f@0 251
f@0 252 SpeechUtilities.changeTabListener(optPane,dialog);
f@0 253 textComponent.addKeyListener(SpeechUtilities.getSpeechKeyListener(true));
f@0 254 textComponent.setEditable(true);
f@0 255 // start the editing sound
f@0 256 SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
f@0 257 dialog.setVisible(true);
f@0 258 dialog.dispose();
f@0 259 SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
f@0 260
f@0 261 if(optPane.getValue() == null)//window closed
f@0 262 return null;
f@0 263 else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel
f@0 264 return null;
f@0 265 else{ // pressed on OK
f@0 266 return textComponent.getText().trim();
f@0 267 }
f@0 268 }
f@0 269
f@0 270 /**
f@0 271 * Shows a dialog with a {@code JComboBox} requesting selection from the user
f@0 272 *
f@0 273 * @param parentComponent the parent {@code Component} for the dialog
f@0 274 * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
f@0 275 * @param options options for the {@code JComboBox}
f@0 276 * @param initialValue the options value selected when the dialog is shown
f@0 277 * @return the option selected by the user
f@0 278 */
f@0 279 public static Object showSelectionDialog(Component parentComponent, String message, Object[] options, Object initialValue){
f@0 280 final LoopComboBox comboBox = new LoopComboBox(options);
f@0 281 comboBox.setSelectedItem(initialValue);
f@0 282 Object[] displayObjects = { new JLabel(message), comboBox };
f@0 283 JOptionPane optPane = new JOptionPane();
f@0 284 optPane.setMessage(displayObjects);
f@0 285 optPane.setMessageType(QUESTION_MESSAGE);
f@0 286 optPane.setOptionType(OK_CANCEL_OPTION);
f@0 287 /* ctrl key will hush the TTS */
f@0 288 optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up");
f@0 289 optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction());
f@0 290
f@0 291 NarratorFactory.getInstance().speak(message+", "+SpeechUtilities.getComponentSpeech(comboBox));
f@0 292 final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.select"));
f@0 293 dialog.addWindowFocusListener(new WindowAdapter(){
f@0 294 @Override
f@0 295 public void windowGainedFocus(WindowEvent e) {
f@0 296 comboBox.requestFocusInWindow();
f@0 297 }
f@0 298 });
f@0 299
f@0 300 comboBox.addItemListener(SpeechUtilities.getSpeechComboBoxItemListener());
f@0 301
f@0 302 SpeechUtilities.changeTabListener(optPane,dialog);
f@0 303 // start the editing sound
f@0 304 SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
f@0 305 dialog.setVisible(true);
f@0 306 dialog.dispose();
f@0 307 SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
f@0 308 if(optPane.getValue() == null)//window closed
f@0 309 return null;
f@0 310 else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel )//pressed on cancel
f@0 311 return null;
f@0 312 else{ // pressed on OK
f@0 313 return comboBox.getSelectedItem();
f@0 314 }
f@0 315 }
f@0 316
f@0 317 /**
f@0 318 * Shows the dialog with a {@code JSpinner} requesting the selection of the speech rate
f@0 319 * of the main voice of the {@code Narrator}
f@0 320 *
f@0 321 * @param parentComponent the parent {@code Component} for the dialog
f@0 322 * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
f@0 323 * @param value the initial value
f@0 324 * @param min the minimum value of the spinner
f@0 325 * @param max the maximum value of the spinner
f@0 326 * @return the selected integer value or {@code null} if the user cancels the dialog
f@0 327 */
f@0 328 public static Integer showNarratorRateDialog(Component parentComponent, String message, int value, int min, int max){
f@0 329 NarratorFactory.getInstance().speak(message);
f@0 330 final JSpinner spinner = new JSpinner(new LoopSpinnerNumberModel(value,min,max));
f@0 331 JFormattedTextField tf = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField();
f@0 332 tf.setEditable(false);
f@0 333 tf.setFocusable(false);
f@0 334 tf.setBackground(Color.white);
f@0 335
f@0 336 Object[] displayObjects = { new JLabel(message), spinner};
f@0 337 final JOptionPane optPane = new JOptionPane();
f@0 338 optPane.setMessage(displayObjects);
f@0 339 optPane.setMessageType(QUESTION_MESSAGE);
f@0 340 optPane.setOptionType(OK_CANCEL_OPTION);
f@0 341 /* ctrl key will hush the TTS */
f@0 342 optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up");
f@0 343 optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction());
f@0 344
f@0 345 final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.input"));
f@0 346 SpeechUtilities.changeTabListener(optPane,dialog);
f@0 347
f@0 348 dialog.addWindowFocusListener(new WindowAdapter(){
f@0 349 @Override
f@0 350 public void windowGainedFocus(WindowEvent e) {
f@0 351 spinner.requestFocusInWindow();
f@0 352 }
f@0 353 });
f@0 354 spinner.addChangeListener(new ChangeListener(){
f@0 355 @Override
f@0 356 public void stateChanged(ChangeEvent evt) {
f@0 357 JSpinner s = (JSpinner)(evt.getSource());
f@0 358 NarratorFactory.getInstance().setRate((Integer)s.getValue());
f@0 359 NarratorFactory.getInstance().speak(s.getValue().toString());
f@0 360 }
f@0 361 });
f@0 362 // start the editing sound
f@0 363 SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
f@0 364 dialog.setVisible(true);
f@0 365 dialog.dispose();
f@0 366 SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
f@0 367
f@0 368 /* set the speech rate back to the value passed as argument */
f@0 369 NarratorFactory.getInstance().setRate(value);
f@0 370 if(optPane.getValue() == null)//window closed
f@0 371 return null;
f@0 372 else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel
f@0 373 return null;
f@0 374 else{ // pressed on OK
f@0 375 return (Integer)spinner.getValue();
f@0 376 }
f@0 377 }
f@0 378
f@0 379 /**
f@0 380 * Brings up a dialog with selected options requesting user to confirmation.
f@0 381 *
f@0 382 * @param parentComponent the parent {@code Component} for the dialog
f@0 383 * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
f@0 384 * @param optionType an integer designating the options available on the dialog
f@0 385 * @return an integer indicating the option selected by the user
f@0 386 */
f@0 387 public static int showConfirmDialog(Component parentComponent, String message, int optionType){
f@0 388 NarratorFactory.getInstance().speak(message);
f@0 389 JOptionPane optPane = new JOptionPane();
f@0 390 optPane.setMessage(message);
f@0 391 optPane.setMessageType(QUESTION_MESSAGE);
f@0 392 optPane.setOptionType(optionType);
f@0 393 /* ctrl key will hush the TTS */
f@0 394 optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up");
f@0 395 optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction());
f@0 396
f@0 397 JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.confirm"));
f@0 398 SpeechUtilities.changeTabListener(optPane,dialog);
f@0 399
f@0 400 SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
f@0 401 dialog.setVisible(true);
f@0 402 dialog.dispose();
f@0 403 SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
f@0 404
f@0 405 if(optPane.getValue() == null)//window closed
f@0 406 return CANCEL_OPTION;
f@0 407 else
f@0 408 return ((Integer)optPane.getValue()).intValue();
f@0 409 }
f@0 410
f@0 411 /**
f@0 412 * Displays a message to the user.
f@0 413 *
f@0 414 * @param parentComponent the parent {@code Component} for the dialog
f@0 415 * @param message the message displayed in the dialog, such text is also uttered by the {@code Narrator}
f@0 416 * @param messageType the type of message to be displayed
f@0 417 */
f@0 418 public static void showMessageDialog(Component parentComponent, String message, int messageType){
f@0 419 NarratorFactory.getInstance().speak(MessageFormat.format(resources.getString("dialog.speech_option_pane.message"), message));
f@0 420 JOptionPane optPane = new JOptionPane();
f@0 421 optPane.setMessage(message);
f@0 422 optPane.setMessageType(messageType);
f@0 423 /* ctrl key will hush the TTS */
f@0 424 optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up");
f@0 425 optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction());
f@0 426
f@0 427 JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.confirm"));
f@0 428 SpeechUtilities.changeTabListener(optPane,dialog);
f@0 429 SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
f@0 430 dialog.setVisible(true);
f@0 431 dialog.dispose();
f@0 432 SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
f@0 433 }
f@0 434
f@0 435 /**
f@0 436 * Displays an error message to the user.
f@0 437 *
f@0 438 * @param parentComponent the parent {@code Component} for the dialog
f@0 439 * @param message the message displayed in the dialog, such text is also uttered by the {@code Narrator}
f@0 440 */
f@0 441 public static void showMessageDialog(Component parentComponent, String message){
f@0 442 showMessageDialog(parentComponent,message,ERROR_MESSAGE);
f@0 443 }
f@0 444
f@0 445 /**
f@0 446 * Execute a ProgressDialogWorker task and
f@0 447 * shows an indeterminate progress bar dialog if the task is not completed after
f@0 448 * {@code millisToDecideToPopup}. The user can use the dialog <i>cancel</i> button
f@0 449 * to cancel the task.
f@0 450 *
f@0 451 * @param <T> the result type returned by the worker
f@0 452 * @param <V> the intermediate result type of the worker
f@0 453 * @param parentComponent the parent {@code Component} for the dialog
f@0 454 * @param message message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
f@0 455 * @param worker a {@code ProgressDialogWorker} that is executed when this method is called
f@0 456 * @param millisToDecideToPopup the millisecond to let to the worker before popping the dialog up
f@0 457 * @return an integer indicating whether the task was completed or it was interrupted by the user
f@0 458 */
f@0 459 public static <T,V> int showProgressDialog(Component parentComponent, String message,final ProgressDialogWorker<T,V> worker, int millisToDecideToPopup){
f@0 460 JProgressBar progressBar = worker.bar;
f@0 461 Object displayObjects[] = {message, progressBar};
f@0 462 final JOptionPane optPane = new JOptionPane(displayObjects);
f@0 463 optPane.setOptionType(DEFAULT_OPTION);
f@0 464 optPane.setOptions(new Object[] {PROGRESS_DIALOG_CANCEL_OPTION});
f@0 465 /* ctrl key will hush the TTS */
f@0 466 optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up");
f@0 467 optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction());
f@0 468
f@0 469 final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.download"));
f@0 470 SpeechUtilities.changeTabListener(optPane,dialog);
f@0 471
f@0 472 worker.setDialog(dialog);
f@0 473 worker.execute();
f@0 474 try {
f@0 475 Thread.sleep(millisToDecideToPopup);
f@0 476 } catch (InterruptedException ie) {
f@0 477 throw new RuntimeException(ie); //should never happen
f@0 478 }
f@0 479 if(worker.isDone())
f@0 480 return OK_OPTION;
f@0 481
f@0 482 NarratorFactory.getInstance().speak(message);
f@0 483 SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
f@0 484 dialog.setVisible(true);
f@0 485 SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
f@0 486 if( optPane.getValue() == null ||
f@0 487 optPane.getValue() == PROGRESS_DIALOG_CANCEL_OPTION ||
f@0 488 Integer.valueOf(CLOSED_OPTION).equals(optPane.getValue())){
f@0 489 worker.cancel(true);
f@0 490 return CANCEL_OPTION;
f@0 491 }
f@0 492 return OK_OPTION;
f@0 493 }
f@0 494
f@0 495 /**
f@0 496 * Shows a check box dialog to select the modifiers of a given property
f@0 497 *
f@0 498 * @param parentComponent the parent {@code Component} for the dialog
f@0 499 * @param message message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
f@0 500 * @param modifierTypes the different types of modifiers that are available for a given property
f@0 501 * @param modifierIndexes the initial selection of modifiers as the dialog is shown
f@0 502 * @return a new set with the modifier indexes selected by the user
f@0 503 */
f@0 504 public static Set<Integer> showModifiersDialog(Component parentComponent, String message, List<String> modifierTypes, Set<Integer> modifierIndexes){
f@0 505 JOptionPane optPane = new JOptionPane();
f@0 506
f@0 507 JPanel checkBoxPanel = new JPanel(new GridLayout(0, 1));
f@0 508 final JCheckBox[] checkBoxes = new JCheckBox[modifierTypes.size()];
f@0 509 for(int i=0;i<checkBoxes.length;i++){
f@0 510 checkBoxes[i] = new JCheckBox(modifierTypes.get(i));
f@0 511 if(modifierIndexes.contains(i))
f@0 512 checkBoxes[i].setSelected(true);
f@0 513 checkBoxPanel.add(checkBoxes[i]);
f@0 514 checkBoxes[i].addItemListener(SpeechUtilities.getCheckBoxSpeechItemListener());
f@0 515 }
f@0 516 NarratorFactory.getInstance().speak(message+" "+SpeechUtilities.getComponentSpeech(checkBoxes[0]));
f@0 517
f@0 518 Object[] displayObjects = {new JLabel(message),checkBoxPanel};
f@0 519 optPane.setMessage(displayObjects);
f@0 520 optPane.setMessageType(QUESTION_MESSAGE);
f@0 521 optPane.setOptionType(OK_CANCEL_OPTION);
f@0 522 /* ctrl key will hush the TTS */
f@0 523 optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up");
f@0 524 optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction());
f@0 525 JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.modifiers"));
f@0 526 SpeechUtilities.changeTabListener(optPane,dialog);
f@0 527
f@0 528 dialog.addWindowFocusListener(new WindowAdapter(){
f@0 529 @Override
f@0 530 public void windowGainedFocus(WindowEvent e) {
f@0 531 checkBoxes[0].requestFocusInWindow();
f@0 532 }
f@0 533 });
f@0 534
f@0 535 SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
f@0 536 dialog.setVisible(true);
f@0 537 dialog.dispose();
f@0 538 SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
f@0 539
f@0 540 if(optPane.getValue() == null)//window closed
f@0 541 return null;
f@0 542 else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel
f@0 543 return null;
f@0 544 else{ // pressed on OK
f@0 545 Set<Integer> returnSet = new LinkedHashSet<Integer>();
f@0 546 for(int i=0;i<checkBoxes.length;i++)
f@0 547 if(checkBoxes[i].isSelected())
f@0 548 returnSet.add(i);
f@0 549 return returnSet;
f@0 550 }
f@0 551 }
f@0 552
f@0 553 /**
f@0 554 * Returns the specified component's {code Frame}.
f@0 555 *
f@0 556 * @param parentComponent the component for this dialog
f@0 557 * @return the {@code Frame} that contains the component
f@0 558 */
f@0 559 public static Frame getFrameForComponent(Component parentComponent){
f@0 560 return JOptionPane.getFrameForComponent(parentComponent);
f@0 561 }
f@0 562
f@0 563 private static ResourceBundle resources = ResourceBundle.getBundle(EditorFrame.class.getName());
f@0 564 private static final int NOTES_TEXT_AREA_COL_SIZE = 10;
f@0 565 private static final int NOTES_TEXT_AREA_ROW_SIZE = 10;
f@0 566 private static final String PROGRESS_DIALOG_CANCEL_OPTION = resources.getString("dialog.speech_option_pane.cancel");
f@0 567
f@0 568
f@0 569 public static final int QUESTION_MESSAGE = JOptionPane.QUESTION_MESSAGE;
f@0 570 public static final int ERROR_MESSAGE = JOptionPane.ERROR_MESSAGE;
f@0 571 public static final int INFORMATION_MESSAGE = JOptionPane.INFORMATION_MESSAGE;
f@0 572 public static final int WARNING_MESSAGE = JOptionPane.WARNING_MESSAGE;
f@0 573 public static final int OK_CANCEL_OPTION = JOptionPane.OK_CANCEL_OPTION;
f@0 574 public static final int CANCEL_OPTION = JOptionPane.CANCEL_OPTION;
f@0 575 public static final int OK_OPTION = JOptionPane.OK_OPTION;
f@0 576 public static final int CLOSED_OPTION = JOptionPane.CLOSED_OPTION;
f@0 577 public static final int DEFAULT_OPTION = JOptionPane.DEFAULT_OPTION;
f@0 578 public static final int YES_NO_OPTION = JOptionPane.YES_NO_OPTION;
f@0 579 public static final int YES_OPTION = JOptionPane.YES_OPTION;
f@0 580 public static final int NO_OPTION = JOptionPane.NO_OPTION;
f@0 581
f@0 582 /**
f@0 583 * A swing worker to be passed as argument to {@code showProgressDialog}. The {@code execute}
f@0 584 * method can be interrupted by the user by clicking on the {@code cancel} button of the dialog.
f@0 585 *
f@0 586 * @param <T> the result type returned by this {@code SwingWorker}'s {@code doInBackground} and {@code get} methods
f@0 587 * @param <V> the type used for carrying out intermediate results by this {@code SwingWorker}'s {@code publish} and {@code process} methods
f@0 588 */
f@0 589 public static abstract class ProgressDialogWorker<T,V> extends SwingWorker<T,V> {
f@0 590 /**
f@0 591 * Creates a new ProgressDialogWorker
f@0 592 */
f@0 593 public ProgressDialogWorker(){
f@0 594 bar = new JProgressBar();
f@0 595 bar.setIndeterminate(true);
f@0 596 }
f@0 597
f@0 598 private void setDialog(JDialog dialog){
f@0 599 this.dialog = dialog;
f@0 600 }
f@0 601
f@0 602 @Override
f@0 603 protected void done() { //executed in EDT when the work is done
f@0 604 if(dialog != null)
f@0 605 dialog.dispose();
f@0 606 }
f@0 607
f@0 608 private JDialog dialog;
f@0 609 private JProgressBar bar;
f@0 610 }
f@0 611
f@0 612
f@0 613 }