public void output(final File file) {
		model.clearScriptQueue();
		MyImageSaver.saveImages(view, file.getParentFile()); // save images first before resourceAddress changes
		resourceAddress = file.toString();
		File xyzFile = new File(FileUtilities.changeExtension(resourceAddress, "xyz"));
		outputXyz(xyzFile);
		if (progressBar != null) {
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					progressBar.setIndeterminate(true);
				}
			});
		}
		view.setResourceAddress(resourceAddress);
		OutputStream os = null;
		try {
			os = new BufferedOutputStream(new FileOutputStream(file));
		}
		catch (IOException e) {
			e.printStackTrace();
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(view), "Error in writing to " + resourceAddress, "Write Error", JOptionPane.ERROR_MESSAGE);
				}
			});
			return;
		}
		XMLEncoder out = new XMLEncoder(os);
		try {
			synchronized (view.getUpdateLock()) {
				encode(out, FileUtilities.getFileName(xyzFile.toString()));
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(view), "Encoding error: " + resourceAddress, "Write Error", JOptionPane.ERROR_MESSAGE);
				}
			});
		}
		finally {
			out.close();
			try {
				os.close();
			}
			catch (IOException iox) {
			}
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					progressBar.setIndeterminate(false);
					runAction.setEnabled(true);
					stopAction.setEnabled(false);
					setProgressMessage("Model saved to " + file);
				}
			});
		}
	}