view java/src/uk/ac/qmul/eecs/ccmi/gui/SpeechOptionPane.java @ 8:ea7885bd9bff tip

fixed bug : render solid line as dotted/dashed when moving the stylus from dotted/dashed to solid
author ccmi-guest
date Thu, 03 Jul 2014 16:12:20 +0100
parents d66dd5880081
children
line wrap: on
line source
/*  
 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.ActionEvent;
import java.awt.event.ActionListener;
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.AbstractAction;
import javax.swing.JButton;
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.Narrator;
import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory;
import uk.ac.qmul.eecs.ccmi.speech.SpeechUtilities;

/**
 * 
 * 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 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 message 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);
		dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		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,(JButton)evt.getSource());
			}
		};
		okButton.addActionListener(buttonListener);
		cancelButton.addActionListener(buttonListener);

		SoundFactory.getInstance().startLoop(SoundEvent.EDITING);
		dialog.setVisible(true);
		SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
		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 the title of this option pane 
	 */
	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 presses 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 source the button that triggered the closing of {@code dialog}
	 */
	protected void onClose(JDialog dialog, JButton source){
		optPane.setValue(source);
		dialog.dispose();
	}
	
	private String title;
	private JOptionPane optPane;
	private JButton okButton;
	private JButton cancelButton;
	
	
	/* -------- STATIC METHODS ----------- */
	
	/**
	 * Shows a dialog with a text area requesting input for the user.
	 * 
	 * @param parentComponent  the parent {@code Component} for the dialog
	 * @param message a displayed in the dialog, such text is also uttered by the {@code Narrator}
	 * @param text the initial text the text area contains when the dialog is displayed 
	 *  
	 * @return the new text entered by the user
	 */
	public static String showTextAreaDialog(Component parentComponent, String message, String text){
		JTextArea textArea = new JTextArea(NOTES_TEXT_AREA_ROW_SIZE,NOTES_TEXT_AREA_COL_SIZE);
		textArea.setText(text);
		NarratorFactory.getInstance().speak(message);
		return textComponentDialog(parentComponent, message, textArea);
	}
	
	/**
	 * Shows a dialog with a text field requesting input from the user 
	 * 
	 * @param parentComponent  the parent {@code Component} for the dialog
	 * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
	 * @param initialSelectionValue the initial text the text field contains when the dialog is displayed 
	 * 
	 * @return the text entered by the user 
	 */
	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);
		dialog.dispose();
		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();
		}
	}	
	
	/**
	 * Shows a dialog with a {@code JComboBox} requesting selection from the user 
	 * 
	 * @param parentComponent  the parent {@code Component} for the dialog
	 * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
	 * @param options options for the {@code JComboBox}
	 * @param initialValue the options value selected when the dialog is shown   
	 * @return the option selected by the user 
	 */
	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);
		dialog.dispose();
		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();
		}
	}
	
	/**
	 * Shows the dialog with a {@code JSpinner} requesting the selection of the speech rate 
	 * of the main voice of the {@code Narrator} 
	 * 
	 * @param parentComponent  the parent {@code Component} for the dialog
	 * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
	 * @param value the initial value 
	 * @param min the minimum value of the spinner 
	 * @param max the maximum value of the spinner 
	 * @return the selected integer value or {@code null} if the user cancels the dialog  
	 */
	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);
		dialog.dispose();
		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();
		}
	}
	
	/**
	 * Brings up a dialog with selected options requesting user to confirmation.
	 * 
	 * @param parentComponent  the parent {@code Component} for the dialog
	 * @param message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
	 * @param optionType  an integer designating the options available on the dialog
	 * @return an integer indicating the option selected by the user 
	 */
	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);
		dialog.dispose();
		SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
		
		if(optPane.getValue() == null)//window closed
			return CANCEL_OPTION;
		else 
			return ((Integer)optPane.getValue()).intValue();
	}
	
	/**
	 * Displays a message to the user.
	 * 
	 * @param parentComponent  the parent {@code Component} for the dialog
	 * @param message the message displayed in the dialog, such text is also uttered by the {@code Narrator}
	 * @param messageType the type of message to be displayed
	 */
	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);
		dialog.dispose();
		SoundFactory.getInstance().stopLoop(SoundEvent.EDITING);
	}
	
	/**
	 * Displays an error message to the user.
	 * 
	 * @param parentComponent the parent {@code Component} for the dialog
	 * @param message the message displayed in the dialog, such text is also uttered by the {@code Narrator}
	 */
	public static void showMessageDialog(Component parentComponent, String message){
		showMessageDialog(parentComponent,message,ERROR_MESSAGE);
	}
	
	/**
	 * Execute a ProgressDialogWorker task and 
	 * shows an indeterminate progress bar dialog if the task is not completed after 
	 * {@code millisToDecideToPopup}. The user can use the dialog <i>cancel</i> button 
	 * to cancel the task. 
	 * 
	 * @param <T>  the result type returned by the worker 
	 * @param <V>  the intermediate result type of the worker 
	 * @param parentComponent  the parent {@code Component} for the dialog
	 * @param message message a message displayed in the dialog, such text is also uttered by the {@code Narrator} 
	 * @param worker a {@code ProgressDialogWorker} that is executed when this method is called
	 * @param millisToDecideToPopup the millisecond to let to the worker before popping the dialog up   
	 * @return an integer indicating whether the task was completed or it was interrupted by the user 
	 */
	public static <T,V> int showProgressDialog(Component parentComponent, String message,final ProgressDialogWorker<T,V> worker, int millisToDecideToPopup){
		JProgressBar progressBar = worker.bar;
		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;
	}
	
	/**
	 * Shows a check box dialog to select the modifiers of a given property 
	 * 
	 * @param parentComponent  the parent {@code Component} for the dialog
	 * @param message message a message displayed in the dialog, such text is also uttered by the {@code Narrator}
	 * @param modifierTypes the different types of modifiers that are available for a given property
	 * @param modifierIndexes the initial selection of modifiers as the dialog is shown
	 * @return a new set with the modifier indexes selected by the user 
	 */
	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);
		dialog.dispose();
		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;
		}
	}
	
	/**
	 * Returns the specified component's {code Frame}.
	 * 
	 * @param parentComponent the component for this dialog 
	 * @return the {@code Frame} that contains the component 
	 */
	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;
	
	/**
	 * A swing worker to be passed as argument to {@code showProgressDialog}. The {@code execute}
	 * method can be interrupted by the user by clicking on the {@code cancel} button of the dialog. 
	 *
	 * @param <T>  the result type returned by this {@code SwingWorker}'s {@code doInBackground} and {@code get} methods
	 * @param <V>  the type used for carrying out intermediate results by this {@code SwingWorker}'s {@code publish} and {@code process} methods
	 */
	public static abstract class ProgressDialogWorker<T,V> extends SwingWorker<T,V> {
		/**
		 * Creates a new ProgressDialogWorker 
		 */
		public ProgressDialogWorker(){
			bar = new JProgressBar();
			bar.setIndeterminate(true);
		}
		
		private void setDialog(JDialog dialog){
			this.dialog = dialog;
		}
		
		@Override
	    protected void done() { //executed in EDT when the work is done
			if(dialog != null)
				dialog.dispose();
		}
		
		private JDialog dialog;
		private JProgressBar bar;
	}
	
	
}