annotate java/src/uk/ac/qmul/eecs/ccmi/gui/FileService.java @ 1:e3935c01cde2 tip

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