view java/src/uk/ac/qmul/eecs/ccmi/gui/filechooser/SpeechFileChooser.java @ 0:78b7fc5391a2

first import, outcome of NIME 2014 hackaton
author Fiore Martin <f.martin@qmul.ac.uk>
date Tue, 08 Jul 2014 16:28:59 +0100
parents
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.filechooser;

import java.awt.Component;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.text.MessageFormat;
import java.util.ResourceBundle;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.filechooser.FileFilter;

import uk.ac.qmul.eecs.ccmi.gui.SpeechOptionPane;
import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory;
import uk.ac.qmul.eecs.ccmi.speech.SpeechUtilities;
import uk.ac.qmul.eecs.ccmi.utils.GridBagUtilities;

/*
 * An accessible file chooser. Users can browse the file system only using hearing as  
 * in the same fashion as they do when exploring a diagram. 
 *
 */
@SuppressWarnings("serial")
class SpeechFileChooser extends JPanel implements FileChooser {
	SpeechFileChooser(){
		super(new GridBagLayout());
		initComponents();
		addComponents();
	}

	private void addComponents() {
		GridBagUtilities gridBag = new GridBagUtilities();
		JScrollPane scrollPane = new JScrollPane(tree); 
		add(scrollPane,gridBag.all());
		add(fileNameLabel,gridBag.label());
		add(fileNameTextField, gridBag.field());
		add(fileTypeLabel, gridBag.label());
		add(fileTypeComboBox, gridBag.field());
	}

	private void initComponents(){		
		resources = ResourceBundle.getBundle(this.getClass().getName());
		/* file name components */
		fileNameLabel = new JLabel(resources.getString("dialog.file_chooser.file_name"));
		fileNameTextField = new TreeSelectionTextField();
		fileNameTextField.setColumns(20);
		fileNameLabel.setLabelFor(fileNameTextField);
		fileNameTextField.addKeyListener(SpeechUtilities.getSpeechKeyListener(true));
		fileTypeLabel = new JLabel(resources.getString("dialog.file_chooser.file_type"));

		/* file type components */
		Object [] items = {new AllFileFilter(resources.getString("all_file_filter.label"))};
		fileTypeComboBox = new JComboBox(items);
		fileTypeLabel.setLabelFor(fileTypeComboBox);

		/* set up the listener binding the tree with the file name and file type components */
		tree = new FileSystemTree((FileFilter)fileTypeComboBox.getSelectedItem());
		tree.addTreeSelectionListener(fileNameTextField);
		fileTypeComboBox.addItemListener(new ItemListener(){
			@Override
			public void itemStateChanged(ItemEvent evt) {
				if(evt.getStateChange() == ItemEvent.SELECTED)
					tree.applyFilter((FileFilter)evt.getItem());
			}
		});
	}

	@Override
	public void setSelectedFile(File file){
		selectedFile = file;	
		if(file == null)
			return;
		tree.setSelectionPath(file);
	}

	@Override
	public File getSelectedFile(){
		return selectedFile;
	}

	@Override
	public void setFileFilter(FileFilter filter){
		if(filter != null){
			FileFilter wrap = new WrapFileFilter(filter);
			((DefaultComboBoxModel)fileTypeComboBox.getModel()).insertElementAt(wrap, 0);
			fileTypeComboBox.getModel().setSelectedItem(wrap);
		}
	}

	@Override
	public void resetChoosableFileFilters(){
		if(fileTypeComboBox.getItemCount() == 2)
			((DefaultComboBoxModel)fileTypeComboBox.getModel()).removeElementAt(0);
	}

	@Override 
	public void setCurrentDirectory(File dir){
		currentDir = dir;
		if(dir == null)
			return;
		tree.setSelectionPath(dir);
	}

	@Override 
	public File getCurrentDirectory(){
		return currentDir;
	}

	@Override
	public int showOpenDialog(Component parent){
		FileSystemTreeNode treeNode = (FileSystemTreeNode)tree.getSelectionPath().getLastPathComponent();
		NarratorFactory.getInstance().speak(
				MessageFormat.format(
						resources.getString("dialog.open.message"),
						treeNode.spokenText()));
		return showDialog(parent,true);
	}

	@Override
	public int showSaveDialog(Component parent){
		FileSystemTreeNode treeNode = (FileSystemTreeNode)tree.getSelectionPath().getLastPathComponent();
		NarratorFactory.getInstance().speak(
				MessageFormat.format(
						resources.getString("dialog.save.message"),
						treeNode.spokenText()));
		return showDialog(parent,false);
	}

	private int showDialog(Component parent, boolean isOpenFileDialog){
		/* overrides on close so that, before closing the dialog it checks that a file name has actually               * 
		 * been entered by the user. If not, the dialog won't close and a error will be notified through the narrator  */
		SpeechOptionPane optionPane = new SpeechOptionPane(resources.getString("dialog.open.title")){
			@Override
			protected void onClose(JDialog dialog, JButton source){
				if(source.equals(getOkButton())){
					if(fileNameTextField.getText().isEmpty()){
						NarratorFactory.getInstance().speak(resources.getString("dialog.error.no_file_name"));
						return;
					}
				}
				super.onClose(dialog, source);
			}
		};
		
		if(isOpenFileDialog)
			optionPane.getOkButton().setText(resources.getString("open_button.label"));
		else
			optionPane.getOkButton().setText(resources.getString("save_button.label"));
		optionPane.getCancelButton().setText(resources.getString("cancel_button.label"));
		
		/* add the speech listener just before showing up and then remove it, otherwise it will talk when filters are added/removed */
		fileTypeComboBox.addItemListener(SpeechUtilities.getSpeechComboBoxItemListener());
		int result = optionPane.showDialog(parent, this);
		fileTypeComboBox.removeItemListener(SpeechUtilities.getSpeechComboBoxItemListener());
		
		if(result == SpeechOptionPane.OK_OPTION){
			FileSystemTreeNode treeNode = (FileSystemTreeNode)tree.getSelectionPath().getLastPathComponent();
			/* user has made his choice. The returned file will be the directory selected in the tree                    * 
			 * or the parent directory of the selected file if a file is selected + the string entered in the JTextField */
			File directory = treeNode.getFile();
			if(!directory.isDirectory())
				directory = directory.getParentFile();
			
			selectedFile = new File(directory,fileNameTextField.getText());
			return APPROVE_OPTION;
		}else{
			return CANCEL_OPTION;
		}
	}

	private ResourceBundle resources;

	private JLabel fileNameLabel;
	private TreeSelectionTextField fileNameTextField;
	private JLabel fileTypeLabel;
	private JComboBox fileTypeComboBox;
	private FileSystemTree tree;
	private File selectedFile;
	private File currentDir;	
}

class AllFileFilter extends FileFilter {
	AllFileFilter(String description){
		this.description = description;
	}

	@Override
	public boolean accept(File file) {
		return true;
	}

	@Override
	public String getDescription() {
		return description;
	}

	@Override
	public String toString(){
		return description;
	}
	String description;
}

class WrapFileFilter extends FileFilter {
	WrapFileFilter(FileFilter delegate){
		this.delegate = delegate;
	}

	@Override
	public boolean accept(File f) {
		return delegate.accept(f);
	}

	@Override
	public String getDescription() {
		return delegate.getDescription();
	}

	@Override
	public String toString(){
		return delegate.getDescription();
	}

	FileFilter delegate;
}