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;
+	}
+	
+	
+}