Mercurial > hg > ccmieditor
diff java/src/uk/ac/qmul/eecs/ccmi/gui/SpeechOptionPane.java @ 0:9418ab7b7f3f
Initial import
author | Fiore Martin <fiore@eecs.qmul.ac.uk> |
---|---|
date | Fri, 16 Dec 2011 17:35:51 +0000 |
parents | |
children | 9e67171477bc |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/src/uk/ac/qmul/eecs/ccmi/gui/SpeechOptionPane.java Fri Dec 16 17:35:51 2011 +0000 @@ -0,0 +1,380 @@ +/* + CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool + + Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package uk.ac.qmul.eecs.ccmi.gui; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.text.MessageFormat; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.ResourceBundle; +import java.util.Set; + +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFormattedTextField; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JSpinner; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import javax.swing.SwingWorker; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.text.JTextComponent; + +import uk.ac.qmul.eecs.ccmi.sound.SoundEvent; +import uk.ac.qmul.eecs.ccmi.sound.SoundFactory; +import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory; +import uk.ac.qmul.eecs.ccmi.speech.SpeechUtilities; + +/** + * + * TheSpeechOptionPane provides one-line calls to display accessible dialog boxes. Input by the user as well + * as focused components are spoken out through text to speech synthesis performed by the {@link Narrator} instance. + * + */ +public abstract class SpeechOptionPane { + + public static String showTextAreaDialog(Component parentComponent, String message, String initialSelectionValue){ + JTextArea textArea = new JTextArea(NOTES_TEXT_AREA_ROW_SIZE,NOTES_TEXT_AREA_COL_SIZE); + textArea.setText(initialSelectionValue); + NarratorFactory.getInstance().speak(message); + return textComponentDialog(parentComponent, message, textArea); + } + + public static String showInputDialog(Component parentComponent, String message, String initialSelectionValue){ + final JTextField textField = new JTextField(initialSelectionValue); + textField.selectAll(); + NarratorFactory.getInstance().speak(message); + return textComponentDialog(parentComponent, message, textField); + } + + private static String textComponentDialog(Component parentComponent, String message, final JTextComponent textComponent){ + Object componentToDisplay = textComponent; + if(textComponent instanceof JTextArea) + componentToDisplay = new JScrollPane(textComponent); + + Object[] displayObjects = { new JLabel(message), componentToDisplay }; + final JOptionPane optPane = new JOptionPane(); + optPane.setMessage(displayObjects); + optPane.setMessageType(QUESTION_MESSAGE); + optPane.setOptionType(OK_CANCEL_OPTION); + /* ctrl key will hush the TTS */ + optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); + optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); + + final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.input")); + if(textComponent instanceof JTextArea) + dialog.setResizable(true); + dialog.addWindowFocusListener(new WindowAdapter(){ + @Override + public void windowGainedFocus(WindowEvent e) { + textComponent.requestFocusInWindow(); + } + }); + + SpeechUtilities.changeTabListener(optPane,dialog); + textComponent.addKeyListener(SpeechUtilities.getSpeechKeyListener(true)); + textComponent.setEditable(true); + // start the editing sound + SoundFactory.getInstance().startLoop(SoundEvent.EDITING); + dialog.setVisible(true); + SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); + + if(optPane.getValue() == null)//window closed + return null; + else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel + return null; + else{ // pressed on OK + return textComponent.getText().trim(); + } + } + + public static String showInputDialog(Component parentComponent, String message){ + return showInputDialog(parentComponent, message, ""); + } + + public static Object showSelectionDialog(Component parentComponent, String message, Object[] options, Object initialValue){ + final LoopComboBox comboBox = new LoopComboBox(options); + comboBox.setSelectedItem(initialValue); + Object[] displayObjects = { new JLabel(message), comboBox }; + JOptionPane optPane = new JOptionPane(); + optPane.setMessage(displayObjects); + optPane.setMessageType(QUESTION_MESSAGE); + optPane.setOptionType(OK_CANCEL_OPTION); + /* ctrl key will hush the TTS */ + optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); + optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); + + NarratorFactory.getInstance().speak(message+", "+SpeechUtilities.getComponentSpeech(comboBox)); + final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.select")); + dialog.addWindowFocusListener(new WindowAdapter(){ + @Override + public void windowGainedFocus(WindowEvent e) { + comboBox.requestFocusInWindow(); + } + }); + + comboBox.addItemListener(SpeechUtilities.getSpeechComboBoxItemListener()); + + SpeechUtilities.changeTabListener(optPane,dialog); + // start the editing sound + SoundFactory.getInstance().startLoop(SoundEvent.EDITING); + dialog.setVisible(true); + SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); + if(optPane.getValue() == null)//window closed + return null; + else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel )//pressed on cancel + return null; + else{ // pressed on OK + return comboBox.getSelectedItem(); + } + } + + public static Integer showNarratorRateDialog(Component parentComponent, String message, int value, int min, int max){ + NarratorFactory.getInstance().speak(message); + final JSpinner spinner = new JSpinner(new LoopSpinnerNumberModel(value,min,max)); + JFormattedTextField tf = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField(); + tf.setEditable(false); + tf.setFocusable(false); + tf.setBackground(Color.white); + + Object[] displayObjects = { new JLabel(message), spinner}; + final JOptionPane optPane = new JOptionPane(); + optPane.setMessage(displayObjects); + optPane.setMessageType(QUESTION_MESSAGE); + optPane.setOptionType(OK_CANCEL_OPTION); + /* ctrl key will hush the TTS */ + optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); + optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); + + final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.input")); + SpeechUtilities.changeTabListener(optPane,dialog); + + dialog.addWindowFocusListener(new WindowAdapter(){ + @Override + public void windowGainedFocus(WindowEvent e) { + spinner.requestFocusInWindow(); + } + }); + spinner.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent evt) { + JSpinner s = (JSpinner)(evt.getSource()); + NarratorFactory.getInstance().setRate((Integer)s.getValue()); + NarratorFactory.getInstance().speak(s.getValue().toString()); + } + }); + // start the editing sound + SoundFactory.getInstance().startLoop(SoundEvent.EDITING); + dialog.setVisible(true); + SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); + + /* set the speech rate back to the value passed as argument */ + NarratorFactory.getInstance().setRate(value); + if(optPane.getValue() == null)//window closed + return null; + else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel + return null; + else{ // pressed on OK + return (Integer)spinner.getValue(); + } + } + + public static int showConfirmDialog(Component parentComponent, String message, int optionType){ + NarratorFactory.getInstance().speak(message); + JOptionPane optPane = new JOptionPane(); + optPane.setMessage(message); + optPane.setMessageType(QUESTION_MESSAGE); + optPane.setOptionType(optionType); + /* ctrl key will hush the TTS */ + optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); + optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); + + JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.confirm")); + SpeechUtilities.changeTabListener(optPane,dialog); + + SoundFactory.getInstance().startLoop(SoundEvent.EDITING); + dialog.setVisible(true); + SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); + + if(optPane.getValue() == null)//window closed + return CANCEL_OPTION; + else + return ((Integer)optPane.getValue()).intValue(); + } + + public static void showMessageDialog(Component parentComponent, String message, int messageType){ + NarratorFactory.getInstance().speak(MessageFormat.format(resources.getString("dialog.speech_option_pane.message"), message)); + JOptionPane optPane = new JOptionPane(); + optPane.setMessage(message); + optPane.setMessageType(messageType); + /* ctrl key will hush the TTS */ + optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); + optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); + + JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.confirm")); + SpeechUtilities.changeTabListener(optPane,dialog); + SoundFactory.getInstance().startLoop(SoundEvent.EDITING); + dialog.setVisible(true); + SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); + } + + public static void showMessageDialog(Component parentComponent, String message){ + showMessageDialog(parentComponent,message,ERROR_MESSAGE); + } + + public static <T,V> int showProgressDialog(Component parentComponent, String message,final ProgressDialogWorker<T,V> worker, int millisToDecideToPopup){ + JProgressBar progressBar = new JProgressBar(); + progressBar.setIndeterminate(true); + Object displayObjects[] = {message, progressBar}; + final JOptionPane optPane = new JOptionPane(displayObjects); + optPane.setOptionType(DEFAULT_OPTION); + optPane.setOptions(new Object[] {PROGRESS_DIALOG_CANCEL_OPTION}); + /* ctrl key will hush the TTS */ + optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); + optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); + + final JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.download")); + SpeechUtilities.changeTabListener(optPane,dialog); + + worker.setDialog(dialog); + worker.execute(); + try { + Thread.sleep(millisToDecideToPopup); + } catch (InterruptedException ie) { + throw new RuntimeException(ie); //should never happen + } + if(worker.isDone()) + return OK_OPTION; + + NarratorFactory.getInstance().speak(message); + SoundFactory.getInstance().startLoop(SoundEvent.EDITING); + dialog.setVisible(true); + SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); + if( optPane.getValue() == null || + optPane.getValue() == PROGRESS_DIALOG_CANCEL_OPTION || + Integer.valueOf(CLOSED_OPTION).equals(optPane.getValue())){ + worker.cancel(true); + return CANCEL_OPTION; + } + return OK_OPTION; + } + + public static Set<Integer> showModifiersDialog(Component parentComponent, String message, List<String> modifierTypes, Set<Integer> modifierIndexes){ + JOptionPane optPane = new JOptionPane(); + + JPanel checkBoxPanel = new JPanel(new GridLayout(0, 1)); + final JCheckBox[] checkBoxes = new JCheckBox[modifierTypes.size()]; + for(int i=0;i<checkBoxes.length;i++){ + checkBoxes[i] = new JCheckBox(modifierTypes.get(i)); + if(modifierIndexes.contains(i)) + checkBoxes[i].setSelected(true); + checkBoxPanel.add(checkBoxes[i]); + checkBoxes[i].addItemListener(SpeechUtilities.getCheckBoxSpeechItemListener()); + } + NarratorFactory.getInstance().speak(message+" "+SpeechUtilities.getComponentSpeech(checkBoxes[0])); + + Object[] displayObjects = {new JLabel(message),checkBoxPanel}; + optPane.setMessage(displayObjects); + optPane.setMessageType(QUESTION_MESSAGE); + optPane.setOptionType(OK_CANCEL_OPTION); + /* ctrl key will hush the TTS */ + optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,InputEvent.CTRL_DOWN_MASK),"shut_up"); + optPane.getActionMap().put("shut_up", SpeechUtilities.getShutUpAction()); + JDialog dialog = optPane.createDialog(parentComponent, resources.getString("dialog.speech_option_pane.modifiers")); + SpeechUtilities.changeTabListener(optPane,dialog); + + dialog.addWindowFocusListener(new WindowAdapter(){ + @Override + public void windowGainedFocus(WindowEvent e) { + checkBoxes[0].requestFocusInWindow(); + } + }); + + SoundFactory.getInstance().startLoop(SoundEvent.EDITING); + dialog.setVisible(true); + SoundFactory.getInstance().stopLoop(SoundEvent.EDITING); + + if(optPane.getValue() == null)//window closed + return null; + else if(((Integer)optPane.getValue()).intValue() == CANCEL_OPTION || ((Integer)optPane.getValue()).intValue() == CLOSED_OPTION)//pressed on cancel + return null; + else{ // pressed on OK + Set<Integer> returnSet = new LinkedHashSet<Integer>(); + for(int i=0;i<checkBoxes.length;i++) + if(checkBoxes[i].isSelected()) + returnSet.add(i); + return returnSet; + } + } + + public static Frame getFrameForComponent(Component parentComponent){ + return JOptionPane.getFrameForComponent(parentComponent); + } + + private static ResourceBundle resources = ResourceBundle.getBundle(EditorFrame.class.getName()); + private static final int NOTES_TEXT_AREA_COL_SIZE = 10; + private static final int NOTES_TEXT_AREA_ROW_SIZE = 10; + private static final String PROGRESS_DIALOG_CANCEL_OPTION = resources.getString("dialog.speech_option_pane.cancel"); + + + public static final int QUESTION_MESSAGE = JOptionPane.QUESTION_MESSAGE; + public static final int ERROR_MESSAGE = JOptionPane.ERROR_MESSAGE; + public static final int INFORMATION_MESSAGE = JOptionPane.INFORMATION_MESSAGE; + public static final int WARNING_MESSAGE = JOptionPane.WARNING_MESSAGE; + public static final int OK_CANCEL_OPTION = JOptionPane.OK_CANCEL_OPTION; + public static final int CANCEL_OPTION = JOptionPane.CANCEL_OPTION; + public static final int OK_OPTION = JOptionPane.OK_OPTION; + public static final int CLOSED_OPTION = JOptionPane.CLOSED_OPTION; + public static final int DEFAULT_OPTION = JOptionPane.DEFAULT_OPTION; + public static final int YES_NO_OPTION = JOptionPane.YES_NO_OPTION; + public static final int YES_OPTION = JOptionPane.YES_OPTION; + public static final int NO_OPTION = JOptionPane.NO_OPTION; + + + public static abstract class ProgressDialogWorker<T,V> extends SwingWorker<T,V> { + private void setDialog(JDialog dialog){ + this.dialog = dialog; + } + + @Override + protected void done() { + if(dialog != null) + dialog.dispose(); + } + + private JDialog dialog; + } + + +}