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@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@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@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@0: * TheSpeechOptionPane provides one-line calls to display accessible dialog boxes. Input by the user as well
fiore@0: * as focused components are spoken out through text to speech synthesis performed by the {@link Narrator} instance.
fiore@0: *
fiore@0: */
fiore@0: public abstract class SpeechOptionPane {
fiore@0:
fiore@0: public static String showTextAreaDialog(Component parentComponent, String message, String initialSelectionValue){
fiore@0: JTextArea textArea = new JTextArea(NOTES_TEXT_AREA_ROW_SIZE,NOTES_TEXT_AREA_COL_SIZE);
fiore@0: textArea.setText(initialSelectionValue);
fiore@0: NarratorFactory.getInstance().speak(message);
fiore@0: return textComponentDialog(parentComponent, message, textArea);
fiore@0: }
fiore@0:
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@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@0: public static String showInputDialog(Component parentComponent, String message){
fiore@0: return showInputDialog(parentComponent, message, "");
fiore@0: }
fiore@0:
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@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@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@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@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@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@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@0: SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
fiore@0: }
fiore@0:
fiore@0: public static void showMessageDialog(Component parentComponent, String message){
fiore@0: showMessageDialog(parentComponent,message,ERROR_MESSAGE);
fiore@0: }
fiore@0:
fiore@0: public static int showProgressDialog(Component parentComponent, String message,final ProgressDialogWorker worker, int millisToDecideToPopup){
fiore@0: JProgressBar progressBar = new JProgressBar();
fiore@0: progressBar.setIndeterminate(true);
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@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 extends SwingWorker {
fiore@0: private void setDialog(JDialog dialog){
fiore@0: this.dialog = dialog;
fiore@0: }
fiore@0:
fiore@0: @Override
fiore@0: protected void done() {
fiore@0: if(dialog != null)
fiore@0: dialog.dispose();
fiore@0: }
fiore@0:
fiore@0: private JDialog dialog;
fiore@0: }
fiore@0:
fiore@0:
fiore@0: }