view java/src/uk/ac/qmul/eecs/ccmi/gui/FileService.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 71ff0735df5a
children d66dd5880081
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.Frame;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ResourceBundle;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import uk.ac.qmul.eecs.ccmi.gui.filechooser.FileChooser;
import uk.ac.qmul.eecs.ccmi.gui.filechooser.FileChooserFactory;
import uk.ac.qmul.eecs.ccmi.sound.SoundEvent;
import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
import uk.ac.qmul.eecs.ccmi.utils.PreferencesService;

public abstract class FileService
{

	/**
	 * An Open object encapsulates the stream, name and path of the file that the user selected for opening.
	 */
	public interface Open
	{
		/**
		 * Gets the input stream corresponding to the user selection.
		 * @return the input stream, or null if the user cancels the file selection task   
		 */
		InputStream getInputStream() throws IOException ;
		/**
		 * Gets the name of the file that the user selected.
		 * @return the file name, or null if the user cancels the file selection task    
		 */
		String getName() throws IOException ;

		/**
		 * Gets the path of the file that the user selected.
		 * @return the file path , or null if the user cancels the file selection task     
		 */
		String getPath() throws IOException;

	}

	/**
	 * A Save object encapsulates the stream and name of the file that the user selected for saving.
	 */
	public interface Save
	{
		/**
		 * Gets the output stream corresponding to the user selection.
		 * @return the output stream, or null if the user cancels the file selection task     
		 */
		OutputStream getOutputStream();
		/**
		 * Gets the name of the file that the user selected.
		 * @return the file name, or null if the user cancels the file selection task 
		 */
		String getName();
		/**
		 * Gets the path of the file that the user selected.
		 * @return the file path, or null if the user cancels the file selection task
		 */
		String getPath();
	}

	/**
	 * This class implements a FileService with a JFileChooser
	 */
	public static class ChooserService 
	{
		public ChooserService(File initialDirectory){
			useAccessible = Boolean.parseBoolean(PreferencesService.getInstance().get("use_accessible_filechooser", "true")); 
			fileChooser = FileChooserFactory.getFileChooser(useAccessible);
			fileChooser.setCurrentDirectory(initialDirectory);
		}

		public FileService.Open open(String defaultDirectory, String defaultFile, 
				ExtensionFilter filter, Frame frame) throws FileNotFoundException {
			checkChangedOption();
			fileChooser.resetChoosableFileFilters();
			fileChooser.setFileFilter(filter);
			if (defaultDirectory != null)
				fileChooser.setCurrentDirectory(new File(defaultDirectory));
			if (defaultFile == null)             
				fileChooser.setSelectedFile(null);
			else
				fileChooser.setSelectedFile(new File(defaultFile));       
			int response = fileChooser.showOpenDialog(frame);         
			if (response == JFileChooser.APPROVE_OPTION)
				return new OpenImpl(fileChooser.getSelectedFile());
			else{
				/* If the user cancels the task (presses cancel button or the X at the top left corner) *
				 * the CANCEl sound is played (together with the registered playerListeenr if any)      */
				if(useAccessible)
					SoundFactory.getInstance().play(SoundEvent.CANCEL);
				return new OpenImpl(null);
			}
		}


		/* If the user cancels the task (presses cancel button or the X at the top left)   *
		 * the CANCEl sound is played (together with the registered playerListeenr if any) */
		public FileService.Save save(String defaultDirectory, String defaultFile, 
				ExtensionFilter filter, String removeExtension, String addExtension, String[] currentTabs) throws IOException {
			checkChangedOption();
			fileChooser.resetChoosableFileFilters();
			fileChooser.setFileFilter(filter);
			if (defaultDirectory == null)
				fileChooser.setCurrentDirectory(new File("."));
			else
				fileChooser.setCurrentDirectory(new File(defaultDirectory));
			if (defaultFile != null){
				File f = new File(editExtension(defaultFile, removeExtension, addExtension));                  
				if(f.exists())
					fileChooser.setSelectedFile(f);
				else
					fileChooser.setSelectedFile(null);
			}else 
				fileChooser.setSelectedFile(null);
			int response = fileChooser.showSaveDialog(null);         
			if (response == JFileChooser.APPROVE_OPTION){
				ResourceBundle resources = ResourceBundle.getBundle(EditorFrame.class.getName());
				File f = fileChooser.getSelectedFile();
				if (addExtension != null && f.getName().indexOf(".") < 0) // no extension supplied
					f = new File(f.getPath() + addExtension);
				
				String fileName = getFileNameFromPath(f.getAbsolutePath(),false);
				for(String tab : currentTabs){
					if(fileName.equals(tab))
						throw new IOException(resources.getString("dialog.error.same_file_name"));
				}
				
				if (!f.exists()) // file doesn't exits return the new SaveImpl with no problems
					return new SaveImpl(f);

				/* file with this name already exists, we must ask the user to confirm */
				if(useAccessible){
					int result = SpeechOptionPane.showConfirmDialog(
							null,
							resources.getString("dialog.overwrite"), 
							SpeechOptionPane.YES_NO_OPTION);
					if (result == SpeechOptionPane.YES_OPTION) 
						return new SaveImpl(f);
				}else{
					int result = JOptionPane.showConfirmDialog(
							null,
							resources.getString("dialog.overwrite"), 
							null,
							JOptionPane.YES_NO_OPTION);
					if (result == JOptionPane.YES_OPTION) 
						return new SaveImpl(f);
				}
			}
			if(useAccessible)
				SoundFactory.getInstance().play(SoundEvent.CANCEL);
			/* returned if the user doesn't want to overwrite the file */ 
			return new SaveImpl(null);
		}

		/* check if the user has changed the configuration since the last time a the fileChooser was shown */ 
		private void checkChangedOption(){
			boolean useAccessible = Boolean.parseBoolean(PreferencesService.getInstance().get("use_accessible_filechooser", "true"));
			if(this.useAccessible != useAccessible){
				this.useAccessible = useAccessible;
				File currentDir = fileChooser.getCurrentDirectory();
				fileChooser = FileChooserFactory.getFileChooser(useAccessible);
				fileChooser.setCurrentDirectory(currentDir);
			}
		}

		private FileChooser fileChooser;
		private boolean useAccessible;
	}

	public static class DirectService {
		public Open open(File file) throws IOException{
			return new OpenImpl(file);
		}

		public Save save(File file) throws IOException{
			return new SaveImpl(file);
		}
	}

	private static class SaveImpl implements FileService.Save{
		public SaveImpl(File f) throws FileNotFoundException{
			if (f != null){
				path = f.getPath();
				name = getFileNameFromPath(path,false); 
				out = new BufferedOutputStream(new FileOutputStream(f));
			}
		}

		@Override
		public String getName() { return name; }
		@Override
		public String getPath() {return path; }
		@Override
		public OutputStream getOutputStream() { return out; }

		private String name;
		private String path;
		private OutputStream out;
	}

	private static class OpenImpl implements FileService.Open
	{
		public OpenImpl(File f) throws FileNotFoundException{
			if (f != null){
				path = f.getPath();
				name = getFileNameFromPath(path,false);
				in = new BufferedInputStream(new FileInputStream(f));
			}
		}

		@Override
		public String getName() { return name; }
		@Override
		public String getPath() { return path; }
		@Override
		public InputStream getInputStream() { return in; }

		private String path;
		private String name;
		private InputStream in;
	}

	/**
   Edits the file path so that it ends in the desired 
   extension.
   @param original the file to use as a starting point
   @param toBeRemoved the extension that is to be
   removed before adding the desired extension. Use
   null if nothing needs to be removed. 
   @param desired the desired extension (e.g. ".png"),
   or a | separated list of extensions
   @return original if it already has the desired 
   extension, or a new file with the edited file path
	 */
	public static String editExtension(String original,
			String toBeRemoved, String desired){
		if (original == null) return null;
		int n = desired.indexOf('|');
		if (n >= 0) desired = desired.substring(0, n);
		String path = original;
		if (!path.toLowerCase().endsWith(desired.toLowerCase())){   		
			if (toBeRemoved != null && path.toLowerCase().endsWith(
					toBeRemoved.toLowerCase()))
				path = path.substring(0, path.length() - toBeRemoved.length());
			path = path + desired;
		}
		return path;      
	}

	public static String getFileNameFromPath(String path,boolean keepExtension){
		int index = path.lastIndexOf(System.getProperty("file.separator"));
		String name;
		if(index == -1)
			name = path;
		else
			name = path.substring(index+1);
		if(!keepExtension){
			index = name.lastIndexOf('.');
			if(index != -1)
				name = name.substring(0, index);
		}
		return name;
	}
}