001 /*
002 * Copyright 2002 - 2007 JEuclid, http://jeuclid.sf.net
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 /* $Id: FileIO.java,v cca61eec2241 2008/05/23 09:53:47 maxberger $ */
018
019 package net.sourceforge.jeuclid.app.mathviewer;
020
021 import java.awt.FileDialog;
022 import java.awt.Frame;
023 import java.io.File;
024 import java.io.FilenameFilter;
025 import java.io.IOException;
026 import java.util.Set;
027
028 import javax.swing.JFileChooser;
029 import javax.swing.JOptionPane;
030
031 import net.sourceforge.jeuclid.MathMLParserSupport;
032 import net.sourceforge.jeuclid.MutableLayoutContext;
033 import net.sourceforge.jeuclid.converter.Converter;
034 import net.sourceforge.jeuclid.converter.ConverterRegistry;
035
036 import org.apache.commons.logging.Log;
037 import org.apache.commons.logging.LogFactory;
038 import org.w3c.dom.Document;
039 import org.w3c.dom.Node;
040 import org.xml.sax.SAXException;
041
042 /**
043 * File I/O support functionality for MathViewer.
044 *
045 * @version $Revision: cca61eec2241 $
046 */
047 public final class FileIO {
048
049 /**
050 * Logger for this class
051 */
052 private static final Log LOGGER = LogFactory.getLog(FileIO.class);
053
054 private static final String EXPORT_ERROR = "MathViewer.exportError"; //$NON-NLS-1$,
055
056 private File lastPath;
057
058 private static final class SingletonHolder {
059 private static FileIO instance = new FileIO();
060
061 private SingletonHolder() {
062 }
063 }
064
065 private FileIO() {
066 }
067
068 /**
069 * Retrieve the FileIO object.
070 *
071 * @return the FileIO object
072 */
073 public static FileIO getInstance() {
074 return FileIO.SingletonHolder.instance;
075 }
076
077 private static String getExtension(final String fileName) {
078 return fileName.substring(fileName.lastIndexOf('.') + 1);
079 }
080
081 private static class SaveExportFilter implements FilenameFilter {
082
083 private final Set<String> extensions;
084
085 protected SaveExportFilter() {
086 this.extensions = ConverterRegistry.getInstance()
087 .getAvailableExtensions();
088 };
089
090 public boolean accept(final File dir, final String name) {
091 return this.extensions.contains(FileIO.getExtension(name));
092 }
093 }
094
095 /**
096 * Select a file.
097 *
098 * @param parent
099 * Frame of the parent
100 * @return A File or null.
101 */
102 public File selectFileToOpen(final Frame parent) {
103 final File selectedFile;
104
105 if (MathViewer.OSX) {
106 // Have to use AWT file chooser for Mac-friendlyness
107 final FileDialog chooser = new FileDialog(parent,
108 "Please select a MathML file");
109 if (this.lastPath != null) {
110 chooser.setDirectory(this.lastPath.toString());
111 }
112 chooser.setVisible(true);
113 final String fileName = chooser.getFile();
114 if (fileName != null) {
115 selectedFile = new File(chooser.getDirectory(), fileName);
116 } else {
117 selectedFile = null;
118 }
119 } else {
120 final JFileChooser fc = new JFileChooser(this.lastPath);
121 final int returnVal = fc.showOpenDialog(parent);
122 if (returnVal == JFileChooser.APPROVE_OPTION) {
123 selectedFile = fc.getSelectedFile();
124 } else {
125 selectedFile = null;
126 }
127 }
128 if (selectedFile != null) {
129 this.lastPath = selectedFile.getParentFile();
130 }
131 return selectedFile;
132 }
133
134 /**
135 * Load the given file.
136 *
137 * @param selectedFile
138 * File object to load.
139 * @param parent
140 * Frame of parent window
141 * @return a parsed Document or null
142 */
143 public Document loadFile(final Frame parent, final File selectedFile) {
144 Document retVal;
145 if (selectedFile == null) {
146 retVal = null;
147 } else {
148 try {
149 retVal = MathMLParserSupport.parseFile(selectedFile);
150 } catch (final SAXException e) {
151 retVal = null;
152 FileIO.LOGGER.warn(e.getMessage(), e);
153 JOptionPane
154 .showMessageDialog(
155 parent,
156 e.getMessage(),
157 Messages.getString("MathViewer.errorParsing"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
158 } catch (final IOException e) {
159 retVal = null;
160 FileIO.LOGGER.warn(e.getMessage(), e);
161 JOptionPane
162 .showMessageDialog(
163 parent,
164 e.getMessage(),
165 Messages
166 .getString("MathViewer.errorAccessing"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
167 }
168 }
169 return retVal;
170 }
171
172 /**
173 * Save a document.
174 *
175 * @param parent
176 * frame of parent.
177 * @param document
178 * the MML document to save.
179 * @param params
180 * rendering parameters.
181 */
182 public void saveDocument(final Frame parent, final Node document,
183 final MutableLayoutContext params) {
184 final File selectedFile;
185
186 if (MathViewer.OSX) {
187 // Have to use AWT file chooser for Mac-friendlyness
188 final FileDialog chooser = new FileDialog(parent, "Export to...",
189 FileDialog.SAVE);
190 if (this.lastPath != null) {
191 chooser.setDirectory(this.lastPath.toString());
192 }
193 chooser.setFilenameFilter(new SaveExportFilter());
194
195 chooser.setVisible(true);
196 final String fileName = chooser.getFile();
197 if (fileName != null) {
198 selectedFile = new File(chooser.getDirectory(), fileName);
199 } else {
200 selectedFile = null;
201 }
202 } else {
203 final JFileChooser fc = new JFileChooser(this.lastPath);
204 final int returnVal = fc.showSaveDialog(parent);
205 if (returnVal == JFileChooser.APPROVE_OPTION) {
206 selectedFile = fc.getSelectedFile();
207 } else {
208 selectedFile = null;
209 }
210
211 }
212 if (selectedFile != null) {
213 this.lastPath = selectedFile.getParentFile();
214
215 FileIO.LOGGER.info(selectedFile);
216
217 int doIt = JOptionPane.YES_OPTION;
218
219 if (selectedFile.exists()) {
220 doIt = JOptionPane.showConfirmDialog(parent, "File "
221 + selectedFile.getName()
222 + " already exists. Overwrite?", "Confirm Overwrite",
223 JOptionPane.YES_NO_OPTION);
224 }
225
226 if (doIt == JOptionPane.YES_OPTION) {
227 this.exportAs(parent, selectedFile, document, params);
228 }
229 }
230 }
231
232 private void exportAs(final Frame parent, final File selectedFile,
233 final Node document, final MutableLayoutContext params) {
234 final String fileName = selectedFile.getName();
235 final String extension = FileIO.getExtension(fileName);
236 final String mimetype = ConverterRegistry.getInstance()
237 .getMimeTypeForSuffix(extension);
238 if (mimetype != null) {
239 try {
240 if (Converter.getInstance().convert(document, selectedFile,
241 mimetype, params) == null) {
242 JOptionPane.showMessageDialog(parent,
243 "Failed to write to " + fileName, Messages
244 .getString(FileIO.EXPORT_ERROR),
245 JOptionPane.ERROR_MESSAGE);
246
247 }
248 } catch (final IOException e) {
249 FileIO.LOGGER.warn(e);
250 JOptionPane.showMessageDialog(parent, e.getMessage(),
251 Messages.getString(FileIO.EXPORT_ERROR),
252 JOptionPane.ERROR_MESSAGE);
253 }
254 } else {
255 JOptionPane.showMessageDialog(parent,
256 "Unsupported file extension " + extension, Messages
257 .getString(FileIO.EXPORT_ERROR),
258 JOptionPane.ERROR_MESSAGE);
259
260 }
261 }
262
263 }