View Javadoc

1   // Copyright 2003-2007, FreeHEP
2   package org.freehep.graphicsio.exportchooser;
3   
4   import java.awt.Component;
5   import java.awt.Dimension;
6   import java.io.BufferedOutputStream;
7   import java.io.File;
8   import java.io.FileOutputStream;
9   import java.io.IOException;
10  import java.io.OutputStream;
11  import java.util.Properties;
12  
13  import javax.swing.JPanel;
14  
15  import org.freehep.graphics2d.VectorGraphics;
16  import org.freehep.graphicsio.MultiPageDocument;
17  import org.freehep.util.export.ExportFileType;
18  
19  /**
20   * 
21   * @author Charles Loomis
22   * @author Mark Donszelmann
23   * @version $Id: AbstractExportFileType.java 12753 2007-06-12 22:32:31Z duns $
24   */
25  public abstract class AbstractExportFileType extends ExportFileType {
26  
27  	public abstract class CancelThread extends Thread {
28  
29  		private boolean stop;
30  
31  		private File currentFile;
32  
33  		private OutputStream currentOut;
34  
35  		ProgressDialog progress;
36  
37  		private CancelThread(ProgressDialog progress) {
38  			super();
39  			this.progress = progress;
40  			this.stop = false;
41  			progress.interruptOnCancel(this);
42  		}
43  
44  		abstract void export() throws IOException;
45  
46  		public void cancel() {
47  			this.stop = true;
48  		}
49  
50  		public boolean isStopped() {
51  			return stop;
52  		}
53  
54  		/**
55  		 * Exports the graphics and afterwards cleans up, i.e. deletes the
56  		 * current file. Hence, current file must be set to null by the
57  		 * subclasses export() method when export is finished. Exceptions will
58  		 * be reported to the ProgressDialog.
59  		 */
60  		public void run() {
61  			try {
62  				export();
63  			} catch (IOException e) {
64  				if (!stop) {
65  					progress.exceptionOccured(e);
66  				}
67  			}
68  			try {
69  				cleanUp();
70  			} catch (IOException e) {
71  				System.err.println("While cleaning up:");
72  				e.printStackTrace();
73  			}
74  		}
75  
76  		void setCurrentFile(File file) {
77  			this.currentFile = file;
78  		}
79  
80  		void setCurrentOutputStream(OutputStream out) {
81  			this.currentOut = out;
82  		}
83  
84  		void cleanUp() throws IOException {
85  			if (currentOut != null)
86  				currentOut.close();
87  			if (currentFile != null)
88  				currentFile.delete();
89  		}
90  	}
91  
92  	private class MultiPageSingleFileExportThread extends CancelThread {
93  
94  		private MultiPageDocument mdoc;
95  
96  		private VectorGraphics graphics;
97  
98  		private Component[] saveTargets;
99  
100 		private MultiPageSingleFileExportThread(MultiPageDocument mdoc,
101 				VectorGraphics g, Component[] saveTargets,
102 				ProgressDialog progress) {
103 
104 			super(progress);
105 			this.mdoc = mdoc;
106 			this.graphics = g;
107 			this.saveTargets = saveTargets;
108 			this.progress = progress;
109 		}
110 
111 		private MultiPageSingleFileExportThread(MultiPageDocument mdoc,
112 				VectorGraphics g, Component[] saveTargets,
113 				ProgressDialog progress, OutputStream out) {
114 			this(mdoc, g, saveTargets, progress);
115 			setCurrentOutputStream(out);
116 		}
117 
118 		private MultiPageSingleFileExportThread(MultiPageDocument mdoc,
119 				VectorGraphics g, Component[] saveTargets,
120 				ProgressDialog progress, File file) {
121 			this(mdoc, g, saveTargets, progress);
122 			setCurrentFile(file);
123 		}
124 
125 		void export() throws IOException {
126 
127 			graphics.startExport();
128 
129 			for (int i = 0; i < saveTargets.length; i++) {
130 				if (isStopped())
131 					return;
132 
133 				// Now actually print the components.
134 				if ((graphics != null) && (mdoc != null)) {
135 					progress.step("Writing page " + (i + 1) + "/"
136 							+ saveTargets.length + ".");
137 					mdoc.openPage(saveTargets[i]);
138 					if (isStopped())
139 						return;
140 					progress.step("Writing page " + (i + 1) + "/"
141 							+ saveTargets.length + "..");
142 					saveTargets[i].print(graphics);
143 					if (isStopped())
144 						return;
145 					progress.step("Writing page " + (i + 1) + "/"
146 							+ saveTargets.length + "...");
147 					mdoc.closePage();
148 					if (isStopped())
149 						return;
150 				}
151 			}
152 			if (isStopped())
153 				return;
154 
155 			progress.step("Writing trailer...");
156 			graphics.endExport();
157 
158 			setCurrentOutputStream(null);
159 			setCurrentFile(null);
160 			progress.dispose();
161 		}
162 	}
163 
164 	private class MultipageMultipleFilesExportThread extends CancelThread {
165 
166 		private File file;
167 
168 		private Component[] saveTargets;
169 
170 		private Component parent;
171 
172 		private Properties properties;
173 
174 		private String creator;
175 
176 		private MultipageMultipleFilesExportThread(Component[] saveTargets,
177 				File file, ProgressDialog progress, Component parent,
178 				Properties properties, String creator) {
179 			super(progress);
180 			this.file = file;
181 			this.saveTargets = saveTargets;
182 			this.parent = parent;
183 			this.properties = properties;
184 			this.creator = creator;
185 		}
186 
187 		void export() throws IOException {
188 			for (int i = 0; i < saveTargets.length; i++) {
189 				if (isStopped()) {
190 					cleanUp();
191 					return;
192 				}
193 				progress.step("Page " + (i + 1) + "/" + saveTargets.length
194 						+ "...");
195 				String filename = file.getAbsolutePath();
196 				int dotIndex = filename.lastIndexOf(".");
197 				if (dotIndex == -1)
198 					dotIndex = filename.length() - 1;
199 				filename = filename.substring(0, dotIndex) + "-" + (i + 1)
200 						+ filename.substring(dotIndex);
201 				File singleFile = new File(filename);
202 				setCurrentFile(singleFile);
203 				exportToFile(singleFile, saveTargets[i], parent, properties,
204 						creator);
205 				setCurrentFile(null);
206 			}
207 			progress.dispose();
208 		}
209 	}
210 
211 	/**
212 	 * Delegates to getGraphics(OutputStream, Component);
213 	 */
214 	public VectorGraphics getGraphics(File file, Component target)
215 			throws IOException {
216 		return getGraphics(
217 				new BufferedOutputStream(new FileOutputStream(file)), target);
218 	}
219 
220 	/**
221 	 * Delegates to getGraphics(OutputStream, Dimension);
222 	 */
223 	public VectorGraphics getGraphics(File file, Dimension dimension)
224 			throws IOException {
225 		return getGraphics(
226 				new BufferedOutputStream(new FileOutputStream(file)), dimension);
227 	}
228 
229 	/**
230 	 * The method returns a graphics context specific for this ExportFileType.
231 	 */
232 	public abstract VectorGraphics getGraphics(OutputStream os,
233 			Component printTarget) throws IOException;
234 
235 	/**
236 	 * Returns a graphics context for this ExportFileType.
237 	 */
238 	public abstract VectorGraphics getGraphics(OutputStream os,
239 			Dimension dimension) throws IOException;
240 
241 	/**
242 	 * Show this dialog and save component as the given file type.
243 	 */
244 	public void exportToFile(OutputStream os, Component target,
245 			Component parent, Properties properties, String creator)
246 			throws IOException {
247 
248 		VectorGraphics g = getGraphics(os, target, properties);
249 		if (g != null) {
250 			g.setCreator(creator);
251 			g.setProperties(properties);
252 			g.startExport();
253 			target.print(g);
254 			g.endExport();
255 		}
256 	}
257 
258 	private VectorGraphics getGraphics(OutputStream os, Component target,
259 			Properties properties) throws IOException {
260 		// NOTE: same as in ExportDialog
261 		int w = Integer.parseInt(properties.getProperty("size-w", "-1"));
262 		int h = Integer.parseInt(properties.getProperty("size-h", "-1"));
263 		return (w >= 0 && h >= 0) ? getGraphics(os, new Dimension(w, h))
264 				: getGraphics(os, target);
265 	}
266 
267 	private VectorGraphics getGraphics(File file, Component target,
268 			Properties properties) throws IOException {
269 		// NOTE: same as in ExportDialog
270 		int w = Integer.parseInt(properties.getProperty("size-w", "-1"));
271 		int h = Integer.parseInt(properties.getProperty("size-h", "-1"));
272 		return (w >= 0 && h >= 0) ? getGraphics(file, new Dimension(w, h))
273 				: getGraphics(file, target);
274 	}
275 
276 	/**
277 	 * Show this dialog and save component as the given file type.
278 	 */
279 	public void exportToFile(File file, Component target, Component parent,
280 			Properties properties, String creator) throws IOException {
281 
282 		exportToFile(new BufferedOutputStream(new FileOutputStream(file)),
283 				target, parent, properties, creator);
284 	}
285 
286 	/**
287 	 * Save all components as the given file type. If
288 	 * <tt>getConfiguredGraphics(OutputStream, Component[])</tt> does not
289 	 * return a <tt>MultiPageDocument</tt> (or null)
290 	 * <tt>saveTargets.length</tt> numbered documents are created each of
291 	 * which contains a single page.
292 	 */
293 	public void exportToFile(OutputStream os, Component[] targets,
294 			Component parent, Properties properties, String creator)
295 			throws IOException {
296 
297 		ProgressDialog progress = null;
298 		Thread exportThread = null;
299 		VectorGraphics g = getGraphics(os, targets[0], properties);
300 		if ((g != null) && (g instanceof MultiPageDocument)) {
301 			g.setCreator(creator);
302 			g.setProperties(properties);
303 			progress = new ProgressDialog(parent, targets.length * 3 + 2,
304 					"Writing header...");
305 			MultiPageDocument mdoc = (MultiPageDocument) g;
306 			mdoc.setMultiPage(true);
307 			exportThread = new MultiPageSingleFileExportThread(mdoc, g,
308 					targets, progress, os);
309 			exportThread.start();
310 			progress.setVisible(true);
311 			IOException exc = progress.getException();
312 			if (exc != null)
313 				throw exc;
314 		} else {
315 			System.out
316 					.println("Cannot write multi files to one output stream.");
317 		}
318 	}
319 
320 	/**
321 	 * Save all components as the given file type. If
322 	 * <tt>getConfiguredGraphics(File, Component[])</tt> does not return a
323 	 * <tt>MultiPageDocument</tt> (or null) <tt>saveTargets.length</tt>
324 	 * numbered documents are created each of which contains a single page.
325 	 */
326 	public void exportToFile(File file, Component[] targets, Component parent,
327 			Properties properties, String creator) throws IOException {
328 
329 		ProgressDialog progress = null;
330 		Thread exportThread = null;
331 		VectorGraphics g = getGraphics(file, targets[0], properties);
332 		if ((g != null) && (g instanceof MultiPageDocument)) {
333 			g.setCreator(creator);
334 			g.setProperties(properties);
335 			progress = new ProgressDialog(parent, targets.length * 3 + 2,
336 					"Writing header...");
337 			MultiPageDocument mdoc = (MultiPageDocument) g;
338 			mdoc.setMultiPage(true);
339 			exportThread = new MultiPageSingleFileExportThread(mdoc, g,
340 					targets, progress, file);
341 		} else {
342 			progress = new ProgressDialog(parent, targets.length + 2,
343 					"Exporting files...");
344 			exportThread = new MultipageMultipleFilesExportThread(targets,
345 					file, progress, parent, properties, creator);
346 		}
347 		exportThread.start();
348 		progress.setVisible(true);
349 		IOException e = progress.getException();
350 		if (e != null)
351 			throw e;
352 	}
353 
354 	public boolean applyChangedOptions(JPanel panel, Properties options) {
355 		if (panel instanceof Options) {
356 			return ((Options) panel).applyChangedOptions(options);
357 		}
358 		System.err
359 				.println(getClass()
360 						+ ": applyChangedOptions(...), panel does not implement Options interface.");
361 		return false;
362 	}
363 }