annotate java/src/uk/ac/qmul/eecs/ccmi/gui/FileService.java @ 4:2c67ac862920

bug fix (correct haptic painting after renaming nodes and after nodes deletion with an edge with more than 2 nodes)
author Fiore Martin <fiore@eecs.qmul.ac.uk>
date Tue, 29 May 2012 15:32:19 +0100
parents 9e67171477bc
children d66dd5880081
rev   line source
fiore@3 1 /*
fiore@3 2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
fiore@3 3
fiore@3 4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
fiore@3 5
fiore@3 6 This program is free software: you can redistribute it and/or modify
fiore@3 7 it under the terms of the GNU General Public License as published by
fiore@3 8 the Free Software Foundation, either version 3 of the License, or
fiore@3 9 (at your option) any later version.
fiore@3 10
fiore@3 11 This program is distributed in the hope that it will be useful,
fiore@3 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
fiore@3 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
fiore@3 14 GNU General Public License for more details.
fiore@3 15
fiore@3 16 You should have received a copy of the GNU General Public License
fiore@3 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
fiore@3 18 */
fiore@0 19 package uk.ac.qmul.eecs.ccmi.gui;
fiore@0 20
fiore@0 21 import java.awt.Frame;
fiore@0 22 import java.io.BufferedInputStream;
fiore@0 23 import java.io.BufferedOutputStream;
fiore@0 24 import java.io.File;
fiore@0 25 import java.io.FileInputStream;
fiore@0 26 import java.io.FileNotFoundException;
fiore@0 27 import java.io.FileOutputStream;
fiore@0 28 import java.io.IOException;
fiore@0 29 import java.io.InputStream;
fiore@0 30 import java.io.OutputStream;
fiore@0 31 import java.util.ResourceBundle;
fiore@0 32
fiore@0 33 import javax.swing.JFileChooser;
fiore@0 34 import javax.swing.JOptionPane;
fiore@0 35
fiore@0 36 import uk.ac.qmul.eecs.ccmi.gui.filechooser.FileChooser;
fiore@0 37 import uk.ac.qmul.eecs.ccmi.gui.filechooser.FileChooserFactory;
fiore@0 38 import uk.ac.qmul.eecs.ccmi.sound.SoundEvent;
fiore@0 39 import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
fiore@0 40 import uk.ac.qmul.eecs.ccmi.utils.PreferencesService;
fiore@0 41
fiore@0 42 public abstract class FileService
fiore@0 43 {
fiore@0 44
fiore@3 45 /**
fiore@3 46 * An Open object encapsulates the stream, name and path of the file that the user selected for opening.
fiore@3 47 */
fiore@3 48 public interface Open
fiore@3 49 {
fiore@3 50 /**
fiore@3 51 * Gets the input stream corresponding to the user selection.
fiore@3 52 * @return the input stream, or null if the user cancels the file selection task
fiore@3 53 */
fiore@3 54 InputStream getInputStream() throws IOException ;
fiore@3 55 /**
fiore@3 56 * Gets the name of the file that the user selected.
fiore@3 57 * @return the file name, or null if the user cancels the file selection task
fiore@3 58 */
fiore@3 59 String getName() throws IOException ;
fiore@0 60
fiore@3 61 /**
fiore@3 62 * Gets the path of the file that the user selected.
fiore@3 63 * @return the file path , or null if the user cancels the file selection task
fiore@3 64 */
fiore@3 65 String getPath() throws IOException;
fiore@0 66
fiore@3 67 }
fiore@0 68
fiore@3 69 /**
fiore@3 70 * A Save object encapsulates the stream and name of the file that the user selected for saving.
fiore@3 71 */
fiore@3 72 public interface Save
fiore@3 73 {
fiore@3 74 /**
fiore@3 75 * Gets the output stream corresponding to the user selection.
fiore@3 76 * @return the output stream, or null if the user cancels the file selection task
fiore@3 77 */
fiore@3 78 OutputStream getOutputStream();
fiore@3 79 /**
fiore@3 80 * Gets the name of the file that the user selected.
fiore@3 81 * @return the file name, or null if the user cancels the file selection task
fiore@3 82 */
fiore@3 83 String getName();
fiore@3 84 /**
fiore@3 85 * Gets the path of the file that the user selected.
fiore@3 86 * @return the file path, or null if the user cancels the file selection task
fiore@3 87 */
fiore@3 88 String getPath();
fiore@3 89 }
fiore@0 90
fiore@3 91 /**
fiore@3 92 * This class implements a FileService with a JFileChooser
fiore@3 93 */
fiore@3 94 public static class ChooserService
fiore@3 95 {
fiore@3 96 public ChooserService(File initialDirectory){
fiore@3 97 useAccessible = Boolean.parseBoolean(PreferencesService.getInstance().get("use_accessible_filechooser", "true"));
fiore@3 98 fileChooser = FileChooserFactory.getFileChooser(useAccessible);
fiore@3 99 fileChooser.setCurrentDirectory(initialDirectory);
fiore@3 100 }
fiore@0 101
fiore@3 102 public FileService.Open open(String defaultDirectory, String defaultFile,
fiore@3 103 ExtensionFilter filter, Frame frame) throws FileNotFoundException {
fiore@3 104 checkChangedOption();
fiore@3 105 fileChooser.resetChoosableFileFilters();
fiore@3 106 fileChooser.setFileFilter(filter);
fiore@3 107 if (defaultDirectory != null)
fiore@3 108 fileChooser.setCurrentDirectory(new File(defaultDirectory));
fiore@3 109 if (defaultFile == null)
fiore@3 110 fileChooser.setSelectedFile(null);
fiore@3 111 else
fiore@3 112 fileChooser.setSelectedFile(new File(defaultFile));
fiore@3 113 int response = fileChooser.showOpenDialog(frame);
fiore@3 114 if (response == JFileChooser.APPROVE_OPTION)
fiore@3 115 return new OpenImpl(fileChooser.getSelectedFile());
fiore@3 116 else{
fiore@3 117 /* If the user cancels the task (presses cancel button or the X at the top left corner) *
fiore@3 118 * the CANCEl sound is played (together with the registered playerListeenr if any) */
fiore@3 119 if(useAccessible)
fiore@3 120 SoundFactory.getInstance().play(SoundEvent.CANCEL);
fiore@3 121 return new OpenImpl(null);
fiore@3 122 }
fiore@3 123 }
fiore@3 124
fiore@3 125
fiore@3 126 /* If the user cancels the task (presses cancel button or the X at the top left) *
fiore@3 127 * the CANCEl sound is played (together with the registered playerListeenr if any) */
fiore@3 128 public FileService.Save save(String defaultDirectory, String defaultFile,
fiore@3 129 ExtensionFilter filter, String removeExtension, String addExtension, String[] currentTabs) throws IOException {
fiore@3 130 checkChangedOption();
fiore@3 131 fileChooser.resetChoosableFileFilters();
fiore@3 132 fileChooser.setFileFilter(filter);
fiore@3 133 if (defaultDirectory == null)
fiore@3 134 fileChooser.setCurrentDirectory(new File("."));
fiore@3 135 else
fiore@3 136 fileChooser.setCurrentDirectory(new File(defaultDirectory));
fiore@3 137 if (defaultFile != null){
fiore@3 138 File f = new File(editExtension(defaultFile, removeExtension, addExtension));
fiore@3 139 if(f.exists())
fiore@3 140 fileChooser.setSelectedFile(f);
fiore@3 141 else
fiore@3 142 fileChooser.setSelectedFile(null);
fiore@3 143 }else
fiore@3 144 fileChooser.setSelectedFile(null);
fiore@3 145 int response = fileChooser.showSaveDialog(null);
fiore@3 146 if (response == JFileChooser.APPROVE_OPTION){
fiore@3 147 ResourceBundle resources = ResourceBundle.getBundle(EditorFrame.class.getName());
fiore@3 148 File f = fileChooser.getSelectedFile();
fiore@3 149 if (addExtension != null && f.getName().indexOf(".") < 0) // no extension supplied
fiore@3 150 f = new File(f.getPath() + addExtension);
fiore@3 151
fiore@3 152 String fileName = getFileNameFromPath(f.getAbsolutePath(),false);
fiore@3 153 for(String tab : currentTabs){
fiore@3 154 if(fileName.equals(tab))
fiore@3 155 throw new IOException(resources.getString("dialog.error.same_file_name"));
fiore@3 156 }
fiore@3 157
fiore@3 158 if (!f.exists()) // file doesn't exits return the new SaveImpl with no problems
fiore@3 159 return new SaveImpl(f);
fiore@3 160
fiore@3 161 /* file with this name already exists, we must ask the user to confirm */
fiore@3 162 if(useAccessible){
fiore@3 163 int result = SpeechOptionPane.showConfirmDialog(
fiore@3 164 null,
fiore@3 165 resources.getString("dialog.overwrite"),
fiore@3 166 SpeechOptionPane.YES_NO_OPTION);
fiore@3 167 if (result == SpeechOptionPane.YES_OPTION)
fiore@3 168 return new SaveImpl(f);
fiore@3 169 }else{
fiore@3 170 int result = JOptionPane.showConfirmDialog(
fiore@3 171 null,
fiore@3 172 resources.getString("dialog.overwrite"),
fiore@3 173 null,
fiore@3 174 JOptionPane.YES_NO_OPTION);
fiore@3 175 if (result == JOptionPane.YES_OPTION)
fiore@3 176 return new SaveImpl(f);
fiore@3 177 }
fiore@3 178 }
fiore@3 179 if(useAccessible)
fiore@3 180 SoundFactory.getInstance().play(SoundEvent.CANCEL);
fiore@3 181 /* returned if the user doesn't want to overwrite the file */
fiore@3 182 return new SaveImpl(null);
fiore@3 183 }
fiore@3 184
fiore@3 185 /* check if the user has changed the configuration since the last time a the fileChooser was shown */
fiore@3 186 private void checkChangedOption(){
fiore@3 187 boolean useAccessible = Boolean.parseBoolean(PreferencesService.getInstance().get("use_accessible_filechooser", "true"));
fiore@3 188 if(this.useAccessible != useAccessible){
fiore@3 189 this.useAccessible = useAccessible;
fiore@3 190 File currentDir = fileChooser.getCurrentDirectory();
fiore@3 191 fileChooser = FileChooserFactory.getFileChooser(useAccessible);
fiore@3 192 fileChooser.setCurrentDirectory(currentDir);
fiore@3 193 }
fiore@3 194 }
fiore@3 195
fiore@3 196 private FileChooser fileChooser;
fiore@3 197 private boolean useAccessible;
fiore@3 198 }
fiore@3 199
fiore@3 200 public static class DirectService {
fiore@3 201 public Open open(File file) throws IOException{
fiore@3 202 return new OpenImpl(file);
fiore@3 203 }
fiore@3 204
fiore@3 205 public Save save(File file) throws IOException{
fiore@3 206 return new SaveImpl(file);
fiore@3 207 }
fiore@3 208 }
fiore@3 209
fiore@3 210 private static class SaveImpl implements FileService.Save{
fiore@3 211 public SaveImpl(File f) throws FileNotFoundException{
fiore@3 212 if (f != null){
fiore@3 213 path = f.getPath();
fiore@3 214 name = getFileNameFromPath(path,false);
fiore@3 215 out = new BufferedOutputStream(new FileOutputStream(f));
fiore@3 216 }
fiore@3 217 }
fiore@3 218
fiore@3 219 @Override
fiore@3 220 public String getName() { return name; }
fiore@3 221 @Override
fiore@3 222 public String getPath() {return path; }
fiore@3 223 @Override
fiore@3 224 public OutputStream getOutputStream() { return out; }
fiore@3 225
fiore@3 226 private String name;
fiore@3 227 private String path;
fiore@3 228 private OutputStream out;
fiore@3 229 }
fiore@3 230
fiore@3 231 private static class OpenImpl implements FileService.Open
fiore@3 232 {
fiore@3 233 public OpenImpl(File f) throws FileNotFoundException{
fiore@3 234 if (f != null){
fiore@3 235 path = f.getPath();
fiore@3 236 name = getFileNameFromPath(path,false);
fiore@3 237 in = new BufferedInputStream(new FileInputStream(f));
fiore@3 238 }
fiore@3 239 }
fiore@3 240
fiore@3 241 @Override
fiore@3 242 public String getName() { return name; }
fiore@3 243 @Override
fiore@3 244 public String getPath() { return path; }
fiore@3 245 @Override
fiore@3 246 public InputStream getInputStream() { return in; }
fiore@3 247
fiore@3 248 private String path;
fiore@3 249 private String name;
fiore@3 250 private InputStream in;
fiore@3 251 }
fiore@3 252
fiore@3 253 /**
fiore@0 254 Edits the file path so that it ends in the desired
fiore@0 255 extension.
fiore@0 256 @param original the file to use as a starting point
fiore@0 257 @param toBeRemoved the extension that is to be
fiore@0 258 removed before adding the desired extension. Use
fiore@0 259 null if nothing needs to be removed.
fiore@0 260 @param desired the desired extension (e.g. ".png"),
fiore@0 261 or a | separated list of extensions
fiore@0 262 @return original if it already has the desired
fiore@0 263 extension, or a new file with the edited file path
fiore@3 264 */
fiore@3 265 public static String editExtension(String original,
fiore@3 266 String toBeRemoved, String desired){
fiore@3 267 if (original == null) return null;
fiore@3 268 int n = desired.indexOf('|');
fiore@3 269 if (n >= 0) desired = desired.substring(0, n);
fiore@3 270 String path = original;
fiore@3 271 if (!path.toLowerCase().endsWith(desired.toLowerCase())){
fiore@3 272 if (toBeRemoved != null && path.toLowerCase().endsWith(
fiore@3 273 toBeRemoved.toLowerCase()))
fiore@3 274 path = path.substring(0, path.length() - toBeRemoved.length());
fiore@3 275 path = path + desired;
fiore@3 276 }
fiore@3 277 return path;
fiore@3 278 }
fiore@3 279
fiore@3 280 public static String getFileNameFromPath(String path,boolean keepExtension){
fiore@3 281 int index = path.lastIndexOf(System.getProperty("file.separator"));
fiore@3 282 String name;
fiore@3 283 if(index == -1)
fiore@3 284 name = path;
fiore@3 285 else
fiore@3 286 name = path.substring(index+1);
fiore@3 287 if(!keepExtension){
fiore@3 288 index = name.lastIndexOf('.');
fiore@3 289 if(index != -1)
fiore@3 290 name = name.substring(0, index);
fiore@3 291 }
fiore@3 292 return name;
fiore@3 293 }
fiore@0 294 }