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 }