fiore@0: /* fiore@0: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool fiore@0: fiore@0: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) fiore@0: fiore@0: This program is free software: you can redistribute it and/or modify fiore@0: it under the terms of the GNU General Public License as published by fiore@0: the Free Software Foundation, either version 3 of the License, or fiore@0: (at your option) any later version. fiore@0: fiore@0: This program is distributed in the hope that it will be useful, fiore@0: but WITHOUT ANY WARRANTY; without even the implied warranty of fiore@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fiore@0: GNU General Public License for more details. fiore@0: fiore@0: You should have received a copy of the GNU General Public License fiore@0: along with this program. If not, see . fiore@0: */ fiore@0: fiore@0: package uk.ac.qmul.eecs.ccmi.gui; fiore@0: fiore@0: import java.awt.Color; fiore@0: import java.awt.Component; fiore@0: import java.awt.Frame; fiore@0: import java.awt.GridLayout; fiore@3: import java.awt.event.ActionEvent; fiore@3: import java.awt.event.ActionListener; fiore@0: import java.awt.event.InputEvent; fiore@0: import java.awt.event.KeyEvent; fiore@0: import java.awt.event.WindowAdapter; fiore@0: import java.awt.event.WindowEvent; fiore@0: import java.text.MessageFormat; fiore@0: import java.util.LinkedHashSet; fiore@0: import java.util.List; fiore@0: import java.util.ResourceBundle; fiore@0: import java.util.Set; fiore@0: fiore@3: import javax.swing.AbstractAction; fiore@3: import javax.swing.JButton; fiore@0: import javax.swing.JCheckBox; fiore@0: import javax.swing.JComponent; fiore@0: import javax.swing.JDialog; fiore@0: import javax.swing.JFormattedTextField; fiore@0: import javax.swing.JLabel; fiore@0: import javax.swing.JOptionPane; fiore@0: import javax.swing.JPanel; fiore@0: import javax.swing.JProgressBar; fiore@0: import javax.swing.JScrollPane; fiore@0: import javax.swing.JSpinner; fiore@0: import javax.swing.JTextArea; fiore@0: import javax.swing.JTextField; fiore@0: import javax.swing.KeyStroke; fiore@0: import javax.swing.SwingWorker; fiore@0: import javax.swing.event.ChangeEvent; fiore@0: import javax.swing.event.ChangeListener; fiore@0: import javax.swing.text.JTextComponent; fiore@0: fiore@0: import uk.ac.qmul.eecs.ccmi.sound.SoundEvent; fiore@0: import uk.ac.qmul.eecs.ccmi.sound.SoundFactory; fiore@3: import uk.ac.qmul.eecs.ccmi.speech.Narrator; fiore@0: import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory; fiore@0: import uk.ac.qmul.eecs.ccmi.speech.SpeechUtilities; fiore@0: fiore@0: /** fiore@0: * fiore@3: * An option panel made out of an {@code Object} being displayed and to buttons: one for accepting and another one for fiore@3: * cancelling the option. fiore@3: * Furthermore, this class provides one-line calls to display accessible dialog boxes. Input by the user as well fiore@3: * as focused components are spoken out through text to speech synthesis performed by a {@link Narrator} instance. fiore@0: */ fiore@3: public class SpeechOptionPane { fiore@3: fiore@3: /** fiore@3: * Construct a new {@code SpeechOptionPane} with no title. The title is displayed at the top of the dialog fiore@3: * that is displayed after a call to {@code showDialog} fiore@3: */ fiore@3: public SpeechOptionPane(){ fiore@3: this(""); fiore@3: } fiore@3: fiore@3: /** fiore@3: * Construct a new {@code SpeechOptionPane} with no title. The title is displayed at the top of the dialog fiore@3: * that is displayed after a call to {@code showDialog} fiore@3: * fiore@3: * @param title the String to be displayed fiore@3: */ fiore@3: public SpeechOptionPane(String title){ fiore@3: this.title = title; fiore@3: okButton = new JButton("OK"); fiore@3: cancelButton = new JButton("Cancel"); fiore@3: } fiore@3: fiore@3: /** fiore@3: * Pops the a dialog holding this SpeechOptionPane fiore@3: * fiore@3: * @param parent the parent component of the dialog fiore@5: * @param message the {@code Object} to display fiore@3: * @return an integer indicating the option selected by the user fiore@3: */ fiore@3: @SuppressWarnings("serial") fiore@3: public int showDialog(Component parent,final Object message){ fiore@3: optPane = new JOptionPane(); fiore@3: optPane.setMessage(message); fiore@3: /* Enter will entail a unique action, regardless the component that's focused */ fiore@3: optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "closeDialog"); fiore@3: optPane.getActionMap().put("closeDialog", new AbstractAction(){ fiore@3: @Override fiore@3: public void actionPerformed(ActionEvent evt) { fiore@3: okButton.doClick(); fiore@3: } fiore@3: }); fiore@3: optPane.setMessageType(JOptionPane.PLAIN_MESSAGE); fiore@3: Object[] options = { fiore@3: okButton, fiore@3: cancelButton fiore@3: }; fiore@3: optPane.setOptions(options); fiore@3: /* ctrl key will hush the TTS */ fiore@3: optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); fiore@3: optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); fiore@3: final JDialog dialog = optPane.createDialog(parent, title); fiore@5: dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); fiore@3: SpeechUtilities.changeTabListener(optPane,dialog); fiore@3: /* when either button is pressed, dialog is disposed and the button itself becomes the optPane.value */ fiore@3: ActionListener buttonListener = new ActionListener(){ fiore@3: @Override fiore@3: public void actionPerformed(ActionEvent evt) { fiore@5: onClose(dialog,(JButton)evt.getSource()); fiore@3: } fiore@3: }; fiore@3: okButton.addActionListener(buttonListener); fiore@3: cancelButton.addActionListener(buttonListener); fiore@3: fiore@3: SoundFactory.getInstance().startLoop(SoundEvent.EDITING); fiore@3: dialog.setVisible(true); fiore@3: SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); fiore@3: if(okButton.equals(optPane.getValue())){ fiore@3: return OK_OPTION; fiore@3: }else{ fiore@3: return CANCEL_OPTION; fiore@3: } fiore@3: } fiore@3: fiore@3: /** fiore@3: * Sets the string appearing at the top of the dialog where this option pane is displayed when {@code showDialog} fiore@3: * is called. fiore@5: * @param title the title of this option pane fiore@3: */ fiore@3: public void setDialogTitle(String title){ fiore@3: this.title = title; fiore@3: } fiore@3: fiore@3: /** fiore@3: * Returns the {@code JButton} that the user has to press (when the option pane is displayed after fiore@3: * {@code showDialog} is called) in order to accept the option. fiore@3: * fiore@3: * @return a reference to the internal {@code JButton} fiore@3: */ fiore@3: public JButton getOkButton(){ fiore@3: return okButton; fiore@3: } fiore@3: fiore@3: /** fiore@3: * Returns the {@code JButton} that the user has to press (when the option pane is displayed after fiore@3: * {@code showDialog} is called) in order to reject the option. fiore@3: * fiore@3: * @return a reference to the internal {@code JButton} fiore@3: */ fiore@3: public JButton getCancelButton(){ fiore@3: return cancelButton; fiore@3: } fiore@3: fiore@3: /** fiore@5: * This method is called just after the user presses either button of the dialog displayed fiore@3: * after {@code showDialog} is called. fiore@3: * It assign a value to the return value and it frees the dialog resources. fiore@3: * It can be overwritten by subclasses but care should be taken of calling this class method via fiore@3: * {@code super} in order to properly close the dialog. fiore@3: * fiore@3: * @param dialog the dialog displayed after {@code showDialog} is called. fiore@3: * @param source the button that triggered the closing of {@code dialog} fiore@3: */ fiore@5: protected void onClose(JDialog dialog, JButton source){ fiore@3: optPane.setValue(source); fiore@3: dialog.dispose(); fiore@3: } fiore@3: fiore@3: private String title; fiore@3: private JOptionPane optPane; fiore@3: private JButton okButton; fiore@3: private JButton cancelButton; fiore@3: fiore@3: fiore@3: /* -------- STATIC METHODS ----------- */ fiore@0: fiore@5: /** fiore@5: * Shows a dialog with a text area requesting input for the user. fiore@5: * fiore@5: * @param parentComponent the parent {@code Component} for the dialog fiore@5: * @param message a displayed in the dialog, such text is also uttered by the {@code Narrator} fiore@5: * @param text the initial text the text area contains when the dialog is displayed fiore@5: * fiore@5: * @return the new text entered by the user fiore@5: */ fiore@5: public static String showTextAreaDialog(Component parentComponent, String message, String text){ fiore@0: JTextArea textArea = new JTextArea(NOTES_TEXT_AREA_ROW_SIZE,NOTES_TEXT_AREA_COL_SIZE); fiore@5: textArea.setText(text); fiore@0: NarratorFactory.getInstance().speak(message); fiore@0: return textComponentDialog(parentComponent, message, textArea); fiore@0: } fiore@0: fiore@5: /** fiore@5: * Shows a dialog with a text field requesting input from the user fiore@5: * fiore@5: * @param parentComponent the parent {@code Component} for the dialog fiore@5: * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator} fiore@5: * @param initialSelectionValue the initial text the text field contains when the dialog is displayed fiore@5: * fiore@5: * @return the text entered by the user fiore@5: */ fiore@0: public static String showInputDialog(Component parentComponent, String message, String initialSelectionValue){ fiore@0: final JTextField textField = new JTextField(initialSelectionValue); fiore@0: textField.selectAll(); fiore@0: NarratorFactory.getInstance().speak(message); fiore@0: return textComponentDialog(parentComponent, message, textField); fiore@0: } fiore@0: fiore@0: private static String textComponentDialog(Component parentComponent, String message, final JTextComponent textComponent){ fiore@0: Object componentToDisplay = textComponent; fiore@0: if(textComponent instanceof JTextArea) fiore@0: componentToDisplay = new JScrollPane(textComponent); fiore@0: fiore@0: Object[] displayObjects = { new JLabel(message), componentToDisplay }; fiore@0: final JOptionPane optPane = new JOptionPane(); fiore@0: optPane.setMessage(displayObjects); fiore@0: optPane.setMessageType(QUESTION_MESSAGE); fiore@0: optPane.setOptionType(OK_CANCEL_OPTION); fiore@0: /* ctrl key will hush the TTS */ fiore@0: optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); fiore@0: optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); fiore@0: fiore@0: final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.input")); fiore@0: if(textComponent instanceof JTextArea) fiore@0: dialog.setResizable(true); fiore@0: dialog.addWindowFocusListener(new WindowAdapter(){ fiore@0: @Override fiore@0: public void windowGainedFocus(WindowEvent e) { fiore@0: textComponent.requestFocusInWindow(); fiore@0: } fiore@0: }); fiore@0: fiore@0: SpeechUtilities.changeTabListener(optPane,dialog); fiore@0: textComponent.addKeyListener(SpeechUtilities.getSpeechKeyListener(true)); fiore@0: textComponent.setEditable(true); fiore@0: // start the editing sound fiore@0: SoundFactory.getInstance().startLoop(SoundEvent.EDITING); fiore@0: dialog.setVisible(true); fiore@5: dialog.dispose(); fiore@0: SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); fiore@0: fiore@0: if(optPane.getValue() == null)//window closed fiore@0: return null; fiore@0: else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel fiore@0: return null; fiore@0: else{ // pressed on OK fiore@0: return textComponent.getText().trim(); fiore@0: } fiore@0: } fiore@0: fiore@5: /** fiore@5: * Shows a dialog with a {@code JComboBox} requesting selection from the user fiore@5: * fiore@5: * @param parentComponent the parent {@code Component} for the dialog fiore@5: * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator} fiore@5: * @param options options for the {@code JComboBox} fiore@5: * @param initialValue the options value selected when the dialog is shown fiore@5: * @return the option selected by the user fiore@5: */ fiore@0: public static Object showSelectionDialog(Component parentComponent, String message, Object[] options, Object initialValue){ fiore@0: final LoopComboBox comboBox = new LoopComboBox(options); fiore@0: comboBox.setSelectedItem(initialValue); fiore@0: Object[] displayObjects = { new JLabel(message), comboBox }; fiore@0: JOptionPane optPane = new JOptionPane(); fiore@0: optPane.setMessage(displayObjects); fiore@0: optPane.setMessageType(QUESTION_MESSAGE); fiore@0: optPane.setOptionType(OK_CANCEL_OPTION); fiore@0: /* ctrl key will hush the TTS */ fiore@0: optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); fiore@0: optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); fiore@0: fiore@0: NarratorFactory.getInstance().speak(message+", "+SpeechUtilities.getComponentSpeech(comboBox)); fiore@0: final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.select")); fiore@0: dialog.addWindowFocusListener(new WindowAdapter(){ fiore@0: @Override fiore@0: public void windowGainedFocus(WindowEvent e) { fiore@0: comboBox.requestFocusInWindow(); fiore@0: } fiore@0: }); fiore@0: fiore@0: comboBox.addItemListener(SpeechUtilities.getSpeechComboBoxItemListener()); fiore@0: fiore@0: SpeechUtilities.changeTabListener(optPane,dialog); fiore@0: // start the editing sound fiore@0: SoundFactory.getInstance().startLoop(SoundEvent.EDITING); fiore@0: dialog.setVisible(true); fiore@5: dialog.dispose(); fiore@0: SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); fiore@0: if(optPane.getValue() == null)//window closed fiore@0: return null; fiore@0: else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel )//pressed on cancel fiore@0: return null; fiore@0: else{ // pressed on OK fiore@0: return comboBox.getSelectedItem(); fiore@0: } fiore@0: } fiore@0: fiore@5: /** fiore@5: * Shows the dialog with a {@code JSpinner} requesting the selection of the speech rate fiore@5: * of the main voice of the {@code Narrator} fiore@5: * fiore@5: * @param parentComponent the parent {@code Component} for the dialog fiore@5: * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator} fiore@5: * @param value the initial value fiore@5: * @param min the minimum value of the spinner fiore@5: * @param max the maximum value of the spinner fiore@5: * @return the selected integer value or {@code null} if the user cancels the dialog fiore@5: */ fiore@0: public static Integer showNarratorRateDialog(Component parentComponent, String message, int value, int min, int max){ fiore@0: NarratorFactory.getInstance().speak(message); fiore@0: final JSpinner spinner = new JSpinner(new LoopSpinnerNumberModel(value,min,max)); fiore@0: JFormattedTextField tf = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField(); fiore@0: tf.setEditable(false); fiore@0: tf.setFocusable(false); fiore@0: tf.setBackground(Color.white); fiore@0: fiore@0: Object[] displayObjects = { new JLabel(message), spinner}; fiore@0: final JOptionPane optPane = new JOptionPane(); fiore@0: optPane.setMessage(displayObjects); fiore@0: optPane.setMessageType(QUESTION_MESSAGE); fiore@0: optPane.setOptionType(OK_CANCEL_OPTION); fiore@0: /* ctrl key will hush the TTS */ fiore@0: optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); fiore@0: optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); fiore@0: fiore@0: final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.input")); fiore@0: SpeechUtilities.changeTabListener(optPane,dialog); fiore@0: fiore@0: dialog.addWindowFocusListener(new WindowAdapter(){ fiore@0: @Override fiore@0: public void windowGainedFocus(WindowEvent e) { fiore@0: spinner.requestFocusInWindow(); fiore@0: } fiore@0: }); fiore@0: spinner.addChangeListener(new ChangeListener(){ fiore@0: @Override fiore@0: public void stateChanged(ChangeEvent evt) { fiore@0: JSpinner s = (JSpinner)(evt.getSource()); fiore@0: NarratorFactory.getInstance().setRate((Integer)s.getValue()); fiore@0: NarratorFactory.getInstance().speak(s.getValue().toString()); fiore@0: } fiore@0: }); fiore@0: // start the editing sound fiore@0: SoundFactory.getInstance().startLoop(SoundEvent.EDITING); fiore@0: dialog.setVisible(true); fiore@5: dialog.dispose(); fiore@0: SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); fiore@0: fiore@0: /* set the speech rate back to the value passed as argument */ fiore@0: NarratorFactory.getInstance().setRate(value); fiore@0: if(optPane.getValue() == null)//window closed fiore@0: return null; fiore@0: else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel fiore@0: return null; fiore@0: else{ // pressed on OK fiore@0: return (Integer)spinner.getValue(); fiore@0: } fiore@0: } fiore@0: fiore@5: /** fiore@5: * Brings up a dialog with selected options requesting user to confirmation. fiore@5: * fiore@5: * @param parentComponent the parent {@code Component} for the dialog fiore@5: * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator} fiore@5: * @param optionType an integer designating the options available on the dialog fiore@5: * @return an integer indicating the option selected by the user fiore@5: */ fiore@0: public static int showConfirmDialog(Component parentComponent, String message, int optionType){ fiore@0: NarratorFactory.getInstance().speak(message); fiore@0: JOptionPane optPane = new JOptionPane(); fiore@0: optPane.setMessage(message); fiore@0: optPane.setMessageType(QUESTION_MESSAGE); fiore@0: optPane.setOptionType(optionType); fiore@0: /* ctrl key will hush the TTS */ fiore@0: optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); fiore@0: optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); fiore@0: fiore@0: JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.confirm")); fiore@0: SpeechUtilities.changeTabListener(optPane,dialog); fiore@0: fiore@0: SoundFactory.getInstance().startLoop(SoundEvent.EDITING); fiore@0: dialog.setVisible(true); fiore@5: dialog.dispose(); fiore@0: SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); fiore@0: fiore@0: if(optPane.getValue() == null)//window closed fiore@0: return CANCEL_OPTION; fiore@0: else fiore@0: return ((Integer)optPane.getValue()).intValue(); fiore@0: } fiore@0: fiore@5: /** fiore@5: * Displays a message to the user. fiore@5: * fiore@5: * @param parentComponent the parent {@code Component} for the dialog fiore@5: * @param message the message displayed in the dialog, such text is also uttered by the {@code Narrator} fiore@5: * @param messageType the type of message to be displayed fiore@5: */ fiore@0: public static void showMessageDialog(Component parentComponent, String message, int messageType){ fiore@0: NarratorFactory.getInstance().speak(MessageFormat.format(resources.getString("dialog.speech_option_pane.message"), message)); fiore@0: JOptionPane optPane = new JOptionPane(); fiore@0: optPane.setMessage(message); fiore@0: optPane.setMessageType(messageType); fiore@0: /* ctrl key will hush the TTS */ fiore@0: optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); fiore@0: optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); fiore@0: fiore@0: JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.confirm")); fiore@0: SpeechUtilities.changeTabListener(optPane,dialog); fiore@0: SoundFactory.getInstance().startLoop(SoundEvent.EDITING); fiore@0: dialog.setVisible(true); fiore@5: dialog.dispose(); fiore@0: SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); fiore@0: } fiore@0: fiore@5: /** fiore@5: * Displays an error message to the user. fiore@5: * fiore@5: * @param parentComponent the parent {@code Component} for the dialog fiore@5: * @param message the message displayed in the dialog, such text is also uttered by the {@code Narrator} fiore@5: */ fiore@0: public static void showMessageDialog(Component parentComponent, String message){ fiore@0: showMessageDialog(parentComponent,message,ERROR_MESSAGE); fiore@0: } fiore@0: fiore@5: /** fiore@5: * Execute a ProgressDialogWorker task and fiore@5: * shows an indeterminate progress bar dialog if the task is not completed after fiore@5: * {@code millisToDecideToPopup}. The user can use the dialog cancel button fiore@5: * to cancel the task. fiore@5: * fiore@5: * @param the result type returned by the worker fiore@5: * @param the intermediate result type of the worker fiore@5: * @param parentComponent the parent {@code Component} for the dialog fiore@5: * @param message message a message displayed in the dialog, such text is also uttered by the {@code Narrator} fiore@5: * @param worker a {@code ProgressDialogWorker} that is executed when this method is called fiore@5: * @param millisToDecideToPopup the millisecond to let to the worker before popping the dialog up fiore@5: * @return an integer indicating whether the task was completed or it was interrupted by the user fiore@5: */ fiore@0: public static int showProgressDialog(Component parentComponent, String message,final ProgressDialogWorker worker, int millisToDecideToPopup){ fiore@3: JProgressBar progressBar = worker.bar; fiore@0: Object displayObjects[] = {message, progressBar}; fiore@0: final JOptionPane optPane = new JOptionPane(displayObjects); fiore@0: optPane.setOptionType(DEFAULT_OPTION); fiore@0: optPane.setOptions(new Object[] {PROGRESS_DIALOG_CANCEL_OPTION}); fiore@0: /* ctrl key will hush the TTS */ fiore@0: optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); fiore@0: optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); fiore@0: fiore@0: final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.download")); fiore@0: SpeechUtilities.changeTabListener(optPane,dialog); fiore@0: fiore@0: worker.setDialog(dialog); fiore@0: worker.execute(); fiore@0: try { fiore@0: Thread.sleep(millisToDecideToPopup); fiore@0: } catch (InterruptedException ie) { fiore@0: throw new RuntimeException(ie); //should never happen fiore@0: } fiore@0: if(worker.isDone()) fiore@0: return OK_OPTION; fiore@0: fiore@0: NarratorFactory.getInstance().speak(message); fiore@0: SoundFactory.getInstance().startLoop(SoundEvent.EDITING); fiore@0: dialog.setVisible(true); fiore@0: SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); fiore@0: if( optPane.getValue() == null || fiore@0: optPane.getValue() == PROGRESS_DIALOG_CANCEL_OPTION || fiore@0: Integer.valueOf(CLOSED_OPTION).equals(optPane.getValue())){ fiore@0: worker.cancel(true); fiore@0: return CANCEL_OPTION; fiore@0: } fiore@0: return OK_OPTION; fiore@0: } fiore@0: fiore@5: /** fiore@5: * Shows a check box dialog to select the modifiers of a given property fiore@5: * fiore@5: * @param parentComponent the parent {@code Component} for the dialog fiore@5: * @param message message a message displayed in the dialog, such text is also uttered by the {@code Narrator} fiore@5: * @param modifierTypes the different types of modifiers that are available for a given property fiore@5: * @param modifierIndexes the initial selection of modifiers as the dialog is shown fiore@5: * @return a new set with the modifier indexes selected by the user fiore@5: */ fiore@0: public static Set showModifiersDialog(Component parentComponent, String message, List modifierTypes, Set modifierIndexes){ fiore@0: JOptionPane optPane = new JOptionPane(); fiore@0: fiore@0: JPanel checkBoxPanel = new JPanel(new GridLayout(0, 1)); fiore@0: final JCheckBox[] checkBoxes = new JCheckBox[modifierTypes.size()]; fiore@0: for(int i=0;i returnSet = new LinkedHashSet(); fiore@0: for(int i=0;i the result type returned by this {@code SwingWorker}'s {@code doInBackground} and {@code get} methods fiore@5: * @param the type used for carrying out intermediate results by this {@code SwingWorker}'s {@code publish} and {@code process} methods fiore@5: */ fiore@0: public static abstract class ProgressDialogWorker extends SwingWorker { fiore@5: /** fiore@5: * Creates a new ProgressDialogWorker fiore@5: */ fiore@3: public ProgressDialogWorker(){ fiore@3: bar = new JProgressBar(); fiore@3: bar.setIndeterminate(true); fiore@3: } fiore@3: fiore@0: private void setDialog(JDialog dialog){ fiore@0: this.dialog = dialog; fiore@0: } fiore@0: fiore@0: @Override fiore@3: protected void done() { //executed in EDT when the work is done fiore@0: if(dialog != null) fiore@0: dialog.dispose(); fiore@0: } fiore@0: fiore@0: private JDialog dialog; fiore@5: private JProgressBar bar; fiore@0: } fiore@0: fiore@0: fiore@0: }