// Copyright 2003-2007, FreeHEP package org.freehep.graphicsio.exportchooser; import java.awt.Component; import java.awt.Dimension; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Properties; import javax.swing.JPanel; import org.freehep.graphics2d.VectorGraphics; import org.freehep.graphicsio.MultiPageDocument; import org.freehep.util.export.ExportFileType; /** * * @author Charles Loomis * @author Mark Donszelmann * @version $Id: AbstractExportFileType.java 12753 2007-06-12 22:32:31Z duns $ */ public abstract class AbstractExportFileType extends ExportFileType { public abstract class CancelThread extends Thread { private boolean stop; private File currentFile; private OutputStream currentOut; ProgressDialog progress; private CancelThread(ProgressDialog progress) { super(); this.progress = progress; this.stop = false; progress.interruptOnCancel(this); } abstract void export() throws IOException; public void cancel() { this.stop = true; } public boolean isStopped() { return stop; } /** * Exports the graphics and afterwards cleans up, i.e. deletes the * current file. Hence, current file must be set to null by the * subclasses export() method when export is finished. Exceptions will * be reported to the ProgressDialog. */ public void run() { try { export(); } catch (IOException e) { if (!stop) { progress.exceptionOccured(e); } } try { cleanUp(); } catch (IOException e) { System.err.println("While cleaning up:"); e.printStackTrace(); } } void setCurrentFile(File file) { this.currentFile = file; } void setCurrentOutputStream(OutputStream out) { this.currentOut = out; } void cleanUp() throws IOException { if (currentOut != null) currentOut.close(); if (currentFile != null) currentFile.delete(); } } private class MultiPageSingleFileExportThread extends CancelThread { private MultiPageDocument mdoc; private VectorGraphics graphics; private Component[] saveTargets; private MultiPageSingleFileExportThread(MultiPageDocument mdoc, VectorGraphics g, Component[] saveTargets, ProgressDialog progress) { super(progress); this.mdoc = mdoc; this.graphics = g; this.saveTargets = saveTargets; this.progress = progress; } private MultiPageSingleFileExportThread(MultiPageDocument mdoc, VectorGraphics g, Component[] saveTargets, ProgressDialog progress, OutputStream out) { this(mdoc, g, saveTargets, progress); setCurrentOutputStream(out); } private MultiPageSingleFileExportThread(MultiPageDocument mdoc, VectorGraphics g, Component[] saveTargets, ProgressDialog progress, File file) { this(mdoc, g, saveTargets, progress); setCurrentFile(file); } void export() throws IOException { graphics.startExport(); for (int i = 0; i < saveTargets.length; i++) { if (isStopped()) return; // Now actually print the components. if ((graphics != null) && (mdoc != null)) { progress.step("Writing page " + (i + 1) + "/" + saveTargets.length + "."); mdoc.openPage(saveTargets[i]); if (isStopped()) return; progress.step("Writing page " + (i + 1) + "/" + saveTargets.length + ".."); saveTargets[i].print(graphics); if (isStopped()) return; progress.step("Writing page " + (i + 1) + "/" + saveTargets.length + "..."); mdoc.closePage(); if (isStopped()) return; } } if (isStopped()) return; progress.step("Writing trailer..."); graphics.endExport(); setCurrentOutputStream(null); setCurrentFile(null); progress.dispose(); } } private class MultipageMultipleFilesExportThread extends CancelThread { private File file; private Component[] saveTargets; private Component parent; private Properties properties; private String creator; private MultipageMultipleFilesExportThread(Component[] saveTargets, File file, ProgressDialog progress, Component parent, Properties properties, String creator) { super(progress); this.file = file; this.saveTargets = saveTargets; this.parent = parent; this.properties = properties; this.creator = creator; } void export() throws IOException { for (int i = 0; i < saveTargets.length; i++) { if (isStopped()) { cleanUp(); return; } progress.step("Page " + (i + 1) + "/" + saveTargets.length + "..."); String filename = file.getAbsolutePath(); int dotIndex = filename.lastIndexOf("."); if (dotIndex == -1) dotIndex = filename.length() - 1; filename = filename.substring(0, dotIndex) + "-" + (i + 1) + filename.substring(dotIndex); File singleFile = new File(filename); setCurrentFile(singleFile); exportToFile(singleFile, saveTargets[i], parent, properties, creator); setCurrentFile(null); } progress.dispose(); } } /** * Delegates to getGraphics(OutputStream, Component); */ public VectorGraphics getGraphics(File file, Component target) throws IOException { return getGraphics( new BufferedOutputStream(new FileOutputStream(file)), target); } /** * Delegates to getGraphics(OutputStream, Dimension); */ public VectorGraphics getGraphics(File file, Dimension dimension) throws IOException { return getGraphics( new BufferedOutputStream(new FileOutputStream(file)), dimension); } /** * The method returns a graphics context specific for this ExportFileType. */ public abstract VectorGraphics getGraphics(OutputStream os, Component printTarget) throws IOException; /** * Returns a graphics context for this ExportFileType. */ public abstract VectorGraphics getGraphics(OutputStream os, Dimension dimension) throws IOException; /** * Show this dialog and save component as the given file type. */ public void exportToFile(OutputStream os, Component target, Component parent, Properties properties, String creator) throws IOException { VectorGraphics g = getGraphics(os, target, properties); if (g != null) { g.setCreator(creator); g.setProperties(properties); g.startExport(); target.print(g); g.endExport(); } } private VectorGraphics getGraphics(OutputStream os, Component target, Properties properties) throws IOException { // NOTE: same as in ExportDialog int w = Integer.parseInt(properties.getProperty("size-w", "-1")); int h = Integer.parseInt(properties.getProperty("size-h", "-1")); return (w >= 0 && h >= 0) ? getGraphics(os, new Dimension(w, h)) : getGraphics(os, target); } private VectorGraphics getGraphics(File file, Component target, Properties properties) throws IOException { // NOTE: same as in ExportDialog int w = Integer.parseInt(properties.getProperty("size-w", "-1")); int h = Integer.parseInt(properties.getProperty("size-h", "-1")); return (w >= 0 && h >= 0) ? getGraphics(file, new Dimension(w, h)) : getGraphics(file, target); } /** * Show this dialog and save component as the given file type. */ public void exportToFile(File file, Component target, Component parent, Properties properties, String creator) throws IOException { exportToFile(new BufferedOutputStream(new FileOutputStream(file)), target, parent, properties, creator); } /** * Save all components as the given file type. If * <tt>getConfiguredGraphics(OutputStream, Component[])</tt> does not * return a <tt>MultiPageDocument</tt> (or null) * <tt>saveTargets.length</tt> numbered documents are created each of * which contains a single page. */ public void exportToFile(OutputStream os, Component[] targets, Component parent, Properties properties, String creator) throws IOException { ProgressDialog progress = null; Thread exportThread = null; VectorGraphics g = getGraphics(os, targets[0], properties); if ((g != null) && (g instanceof MultiPageDocument)) { g.setCreator(creator); g.setProperties(properties); progress = new ProgressDialog(parent, targets.length * 3 + 2, "Writing header..."); MultiPageDocument mdoc = (MultiPageDocument) g; mdoc.setMultiPage(true); exportThread = new MultiPageSingleFileExportThread(mdoc, g, targets, progress, os); exportThread.start(); progress.setVisible(true); IOException exc = progress.getException(); if (exc != null) throw exc; } else { System.out .println("Cannot write multi files to one output stream."); } } /** * Save all components as the given file type. If * <tt>getConfiguredGraphics(File, Component[])</tt> does not return a * <tt>MultiPageDocument</tt> (or null) <tt>saveTargets.length</tt> * numbered documents are created each of which contains a single page. */ public void exportToFile(File file, Component[] targets, Component parent, Properties properties, String creator) throws IOException { ProgressDialog progress = null; Thread exportThread = null; VectorGraphics g = getGraphics(file, targets[0], properties); if ((g != null) && (g instanceof MultiPageDocument)) { g.setCreator(creator); g.setProperties(properties); progress = new ProgressDialog(parent, targets.length * 3 + 2, "Writing header..."); MultiPageDocument mdoc = (MultiPageDocument) g; mdoc.setMultiPage(true); exportThread = new MultiPageSingleFileExportThread(mdoc, g, targets, progress, file); } else { progress = new ProgressDialog(parent, targets.length + 2, "Exporting files..."); exportThread = new MultipageMultipleFilesExportThread(targets, file, progress, parent, properties, creator); } exportThread.start(); progress.setVisible(true); IOException e = progress.getException(); if (e != null) throw e; } public boolean applyChangedOptions(JPanel panel, Properties options) { if (panel instanceof Options) { return ((Options) panel).applyChangedOptions(options); } System.err .println(getClass() + ": applyChangedOptions(...), panel does not implement Options interface."); return false; } }