annotate java/src/uk/ac/qmul/eecs/ccmi/gui/SpeechOptionPane.java @ 8:ea7885bd9bff tip

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