package com.horstmann.violet.framework.file; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JOptionPane; import com.horstmann.violet.framework.dialog.DialogFactory; import com.horstmann.violet.framework.file.chooser.IFileChooserService; import com.horstmann.violet.framework.file.export.FileExportService; import com.horstmann.violet.framework.file.naming.ExtensionFilter; import com.horstmann.violet.framework.file.naming.FileNamingService; import com.horstmann.violet.framework.file.persistence.IFilePersistenceService; import com.horstmann.violet.framework.file.persistence.IFileReader; import com.horstmann.violet.framework.file.persistence.IFileWriter; import com.horstmann.violet.framework.file.persistence.JFileWriter; import com.horstmann.violet.framework.injection.bean.ManiocFramework.BeanInjector; import com.horstmann.violet.framework.injection.bean.ManiocFramework.InjectedBean; import com.horstmann.violet.framework.injection.resources.ResourceBundleInjector; import com.horstmann.violet.framework.injection.resources.annotation.ResourceBundleBean; import com.horstmann.violet.framework.printer.PrintEngine; import com.horstmann.violet.product.diagram.abstracts.IGraph; public class GraphFile implements IGraphFile { /** * Creates a new graph file with a new graph instance * * @param graphClass */ public GraphFile(Class<? extends IGraph> graphClass) { ResourceBundleInjector.getInjector().inject(this); BeanInjector.getInjector().inject(this); try { this.graph = graphClass.newInstance(); this.autoSaveFilename = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime()) + ".html"; this.autoSaveFile = new File(this.autoSaveDirectory + this.autoSaveFilename); this.autoSaveFile.createNewFile(); } catch (Exception e) { DialogFactory.getInstance().showErrorDialog(e.getMessage()); throw new RuntimeException(e); } } /** * Constructs a graph file from an existing file * * @param file */ public GraphFile(IFile file) throws IOException { ResourceBundleInjector.getInjector().inject(this); BeanInjector.getInjector().inject(this); IFileReader fileOpener = fileChooserService.getFileReader(file); if (fileOpener == null) { throw new IOException("Open file action cancelled by user"); } InputStream in = fileOpener.getInputStream(); if (in != null) { this.graph = this.filePersistenceService.read(in); this.autoSaveFilename = file.getFilename(); this.autoSaveFile = new File(this.autoSaveDirectory + this.autoSaveFilename); this.autoSaveFile.createNewFile(); } else { throw new IOException("Unable to read file " + fileOpener.getFileDefinition().getFilename() + " from location " + fileOpener.getFileDefinition().getDirectory()); } } @Override public IGraph getGraph() { return this.graph; } @Override public String getFilename() { return this.currentFilename; } @Override public String getDirectory() { return this.currentDirectory; } @Override public void setSaveRequired() { this.isSaveRequired = true; fireGraphModified(); } @Override public boolean isSaveRequired() { return this.isSaveRequired; } /** * Indicates if this file is new * * @return b */ private boolean isNewFile() { if (this.currentFilename == null && this.currentDirectory == null) { return true; } return false; } @Override public void save() { if (this.isNewFile()) { saveToNewLocation(); return; } try { IFileWriter fileSaver = getFileSaver(false); OutputStream outputStream = fileSaver.getOutputStream(); this.filePersistenceService.write(this.graph, outputStream); this.isSaveRequired = false; fireGraphSaved(); this.currentFilename = fileSaver.getFileDefinition().getFilename(); this.currentDirectory = fileSaver.getFileDefinition().getDirectory(); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void autoSave() { try { if (autoSaveFile.exists()) { JFileWriter jfilewriter = new JFileWriter(autoSaveFile); this.filePersistenceService.write(this.graph, jfilewriter.getOutputStream()); } } catch (Exception e) { throw new RuntimeException(e); } } @Override public void removeBackup() { if (autoSaveFile.exists()) autoSaveFile.delete(); } @Override public void saveToNewLocation() { try { IFileWriter fileSaver = getFileSaver(true); if (fileSaver == null) { // This appends when the action is cancelled return; } OutputStream outputStream = fileSaver.getOutputStream(); this.filePersistenceService.write(this.graph, outputStream); this.isSaveRequired = false; this.currentFilename = fileSaver.getFileDefinition().getFilename(); this.currentDirectory = fileSaver.getFileDefinition().getDirectory(); fireGraphSaved(); } catch (IOException e1) { String message = MessageFormat.format(fileExportErrorMessage, e1.getMessage()); JOptionPane.showMessageDialog(null, message, fileExportError, JOptionPane.ERROR_MESSAGE); } } /** * Returns a IFileSaver instance. Then, this object allows to save graph content. If the graph has never been saved, the * FileChooserService<br/> * will open a dialog box to select a location. If not, the returned IFileSaver will automatically be bound to the last saving * location.<br/> * You can also force the FileChooserService to open the dialog box with the given argument.<br/> * * @param isAskedForNewLocation if true, then the FileChooser will open a dialog box to allow to choice a new location * @return f */ private IFileWriter getFileSaver(boolean isAskedForNewLocation) { try { if (isAskedForNewLocation) { ExtensionFilter extensionFilter = this.fileNamingService.getExtensionFilter(this.graph); ExtensionFilter[] array = { extensionFilter }; return this.fileChooserService.chooseAndGetFileWriter(array); } return this.fileChooserService.getFileWriter(this); } catch (IOException e1) { String message = MessageFormat.format(fileExportErrorMessage, e1.getMessage()); JOptionPane.showMessageDialog(null, message, fileExportError, JOptionPane.ERROR_MESSAGE); return null; } } @Override public void addListener(IGraphFileListener listener) { synchronized (listeners) { listeners.add(listener); } } @Override public void removeListener(IGraphFileListener listener) { synchronized (listeners) { listeners.remove(listener); } } /** * Sends an event to listeners each time the graph is modified */ private void fireGraphModified() { synchronized (listeners) { for (IGraphFileListener listener : listeners) { listener.onFileModified(); } } } /** * Sends an event to listeners when the graph has been saved */ private void fireGraphSaved() { synchronized (listeners) { for (IGraphFileListener listener : listeners) { listener.onFileSaved(); } } } @Override public void exportToClipboard() { FileExportService.exportToclipBoard(this.graph); JOptionPane optionPane = new JOptionPane(); optionPane.setIcon(this.clipBoardDialogIcon); optionPane.setMessage(this.clipBoardDialogMessage); optionPane.setName(this.clipBoardDialogTitle); this.dialogFactory.showDialog(optionPane, this.clipBoardDialogTitle, true); } @Override public void exportImage(OutputStream out, String format) { if (!ImageIO.getImageWritersByFormatName(format).hasNext()) { MessageFormat formatter = new MessageFormat(this.exportImageErrorMessage); String message = formatter.format(new Object[] { format }); JOptionPane optionPane = new JOptionPane(); optionPane.setMessage(message); this.dialogFactory.showDialog(optionPane, this.exportImageDialogTitle, true); return; } try { try { ImageIO.write(FileExportService.getImage(this.graph), format, out); } finally { out.close(); } } catch (Exception e) { throw new RuntimeException(e); } } @Override public void exportToPdf(OutputStream out) { FileExportService.exportToPdf(graph, out); } @Override public void exportToPrinter() { PrintEngine engine = new PrintEngine(this.graph); engine.start(); } private IGraph graph; /** * Needed to identify the physical file used to save the graph */ private String currentFilename; private String autoSaveFilename; /** * Needed to identify the physical file used to save the graph */ private String currentDirectory; private final String autoSaveDirectory = System.getProperty("user.home") + File.separator + "VioletUML" + File.separator; private boolean isSaveRequired = false; @ResourceBundleBean(key = "dialog.export_to_clipboard.icon") private ImageIcon clipBoardDialogIcon; @ResourceBundleBean(key = "dialog.export_to_clipboard.title") private String clipBoardDialogTitle; @ResourceBundleBean(key = "dialog.export_to_clipboard.ok") private String clipBoardDialogMessage; @ResourceBundleBean(key = "dialog.error.unsupported_image") private String exportImageErrorMessage; @ResourceBundleBean(key = "dialog.error.title") private String exportImageDialogTitle; @InjectedBean private IFileChooserService fileChooserService; @InjectedBean private FileNamingService fileNamingService; @InjectedBean private IFilePersistenceService filePersistenceService; @ResourceBundleBean(key = "file.export.error.message") private String fileExportErrorMessage; @ResourceBundleBean(key = "file.export.error") private String fileExportError; @InjectedBean private DialogFactory dialogFactory; private List<IGraphFileListener> listeners = new ArrayList<IGraphFileListener>(); private File autoSaveFile; }