diff java/src/uk/ac/qmul/eecs/ccmi/gui/SpeechOptionPane.java @ 3:9e67171477bc

PHANTOM Omni Heptic device release
author Fiore Martin <fiore@eecs.qmul.ac.uk>
date Wed, 25 Apr 2012 17:09:09 +0100
parents 9418ab7b7f3f
children d66dd5880081
line wrap: on
line diff
--- a/java/src/uk/ac/qmul/eecs/ccmi/gui/SpeechOptionPane.java	Mon Feb 06 12:54:06 2012 +0000
+++ b/java/src/uk/ac/qmul/eecs/ccmi/gui/SpeechOptionPane.java	Wed Apr 25 17:09:09 2012 +0100
@@ -23,6 +23,8 @@
 import java.awt.Component;
 import java.awt.Frame;
 import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.WindowAdapter;
@@ -33,6 +35,8 @@
 import java.util.ResourceBundle;
 import java.util.Set;
 
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JComponent;
 import javax.swing.JDialog;
@@ -53,16 +57,144 @@
 
 import uk.ac.qmul.eecs.ccmi.sound.SoundEvent;
 import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
+import uk.ac.qmul.eecs.ccmi.speech.Narrator;
 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. 
+ * An option panel made out of an {@code Object} being displayed and to buttons: one for accepting and another one for 
+ * cancelling the option.   
+ * Furthermore, this class 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 a {@link Narrator} instance.
+ *   
  *  
  */
-public abstract class SpeechOptionPane {
+public class SpeechOptionPane {
+	
+	/**
+	 * Construct a new {@code SpeechOptionPane} with no title. The title is displayed at the top of the dialog
+	 * that is displayed after a call to {@code showDialog} 
+	 */
+	public SpeechOptionPane(){
+		this("");
+	}
+	
+	/**
+	 * Construct a new {@code SpeechOptionPane} with no title. The title is displayed at the top of the dialog
+	 * that is displayed after a call to {@code showDialog}
+	 * 
+	 * @param title the String to be displayed
+	 */
+	public SpeechOptionPane(String title){
+		this.title = title; 
+		okButton = new JButton("OK");
+		cancelButton = new JButton("Cancel");
+	}
+	
+	/**
+	 * Pops the a dialog holding this SpeechOptionPane 
+	 *  
+	 * @param parent the parent component of the dialog
+	 * @param the {@code Object} to display
+	 * @return an integer indicating the option selected by the user
+	 */
+	@SuppressWarnings("serial")
+	public int showDialog(Component parent,final Object message){
+		optPane = new JOptionPane();
+		optPane.setMessage(message);
+		/* Enter will entail a unique action, regardless the component that's focused */
+		optPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "closeDialog");
+		optPane.getActionMap().put("closeDialog", new AbstractAction(){
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				okButton.doClick();
+			}
+		});
+		optPane.setMessageType(JOptionPane.PLAIN_MESSAGE);
+		Object[] options = {
+				okButton,
+				cancelButton
+		};
+		optPane.setOptions(options);
+		/* 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(parent, title);
+		SpeechUtilities.changeTabListener(optPane,dialog);
+		/* when either button is pressed, dialog is disposed and the button itself becomes the optPane.value */
+		ActionListener buttonListener = new ActionListener(){
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				onClose(dialog,message,(JButton)evt.getSource());
+			}
+		};
+		okButton.addActionListener(buttonListener);
+		cancelButton.addActionListener(buttonListener);
+
+		SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
+		dialog.setVisible(true);
+		SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
+		dialog.dispose();
+		if(okButton.equals(optPane.getValue())){
+			return OK_OPTION;
+		}else{
+			return CANCEL_OPTION;
+		}
+	}
+	
+	/**
+	 * Sets the string appearing at the top of the dialog where this option pane is displayed when {@code showDialog}
+	 * is called.
+	 * @param title
+	 */
+	public void setDialogTitle(String title){
+		this.title = title;
+	}
+	
+	/**
+	 * Returns the {@code JButton} that the user has to press (when the option pane is displayed after 
+	 * {@code showDialog} is called) in order to accept the option.
+	 *    
+	 * @return a reference to the internal {@code JButton} 
+	 */
+	public JButton getOkButton(){
+		return okButton;
+	}
+	
+	/**
+	 * Returns the {@code JButton} that the user has to press (when the option pane is displayed after 
+	 * {@code showDialog} is called) in order to reject the option.
+	 *    
+	 * @return a reference to the internal {@code JButton} 
+	 */
+	public JButton getCancelButton(){
+		return cancelButton;
+	}
+	
+	/**
+	 * This method is called just after the user pressed either button of the dialog displayed
+	 * after {@code showDialog} is called.
+	 * It assign a value to the return value and it frees the dialog resources.
+	 * It can be overwritten by subclasses but care should be taken of calling this class method via
+	 * {@code super} in order to properly close the dialog.   
+	 * 
+	 * @param dialog the dialog displayed after {@code showDialog} is called. 
+	 * @param message
+	 * @param source the button that triggered the closing of {@code dialog}
+	 */
+	protected void onClose(JDialog dialog,Object message, JButton source){
+		optPane.setValue(source);
+		dialog.dispose();
+	}
+	
+	private String title;
+	private JOptionPane optPane;
+	private JButton okButton;
+	private JButton cancelButton;
+	
+	
+	/* -------- STATIC METHODS ----------- */
 	
 	public static String showTextAreaDialog(Component parentComponent, String message, String initialSelectionValue){
 		JTextArea textArea = new JTextArea(NOTES_TEXT_AREA_ROW_SIZE,NOTES_TEXT_AREA_COL_SIZE);
@@ -254,8 +386,7 @@
 	}
 	
 	public static <T,V> int showProgressDialog(Component parentComponent, String message,final ProgressDialogWorker<T,V> worker, int millisToDecideToPopup){
-		JProgressBar progressBar = new JProgressBar();
-		progressBar.setIndeterminate(true);
+		JProgressBar progressBar = worker.bar;
 		Object displayObjects[] = {message, progressBar};
 		final JOptionPane optPane = new JOptionPane(displayObjects);
 		optPane.setOptionType(DEFAULT_OPTION);
@@ -363,17 +494,23 @@
 	
 	
 	public static abstract class ProgressDialogWorker<T,V> extends SwingWorker<T,V> {
+		public ProgressDialogWorker(){
+			bar = new JProgressBar();
+			bar.setIndeterminate(true);
+		}
+		
 		private void setDialog(JDialog dialog){
 			this.dialog = dialog;
 		}
 		
 		@Override
-	    protected void done() {
+	    protected void done() { //executed in EDT when the work is done
 			if(dialog != null)
 				dialog.dispose();
 		}
 		
 		private JDialog dialog;
+		protected JProgressBar bar;
 	}