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 }
|