/* * @(#)ExportFileAction.java * * Copyright (c) 1996-2010 The authors and contributors of JHotDraw. * You may not use, copy or modify this file, except in compliance with the * accompanying license terms. */ package org.jhotdraw.app.action.file; import edu.umd.cs.findbugs.annotations.Nullable; import java.net.URISyntaxException; import java.util.logging.Level; import java.util.logging.Logger; import org.jhotdraw.gui.*; import org.jhotdraw.gui.event.*; import org.jhotdraw.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; import java.net.URI; import java.util.prefs.Preferences; import org.jhotdraw.app.*; import org.jhotdraw.app.action.AbstractViewAction; import org.jhotdraw.gui.JFileURIChooser; import org.jhotdraw.gui.URIChooser; import org.jhotdraw.gui.filechooser.ExtensionFileFilter; import org.jhotdraw.net.URIUtil; /** * Presents a file chooser to the user and then exports the contents of the * active view to the chosen file. * <p> * This action requires that {@link ApplicationModel#createExportChooser} * creates an appropriate {@link URIChooser}. * <p> * This action is called when the user selects the Export item in the File * menu. The menu item is automatically created by the application. * <p> * When the {@code proposeFileName} property is set on the action, the action * will propose the file name without an extension in the URI chooser. * Otherwise, the file name will be left empty. * <p> * If you want this behavior in your application, you have to create an action * with this ID and put it in your {@code ApplicationModel} in method * {@link ApplicationModel#initApplication}. * <hr> * <b>Features</b> * * <p><em>Allow multiple views for URI</em><br> * When the feature is disabled, {@code ExportFileAction} prevents exporting to an URI which * is opened in another view.<br> * See {@link org.jhotdraw.app} for a description of the feature. * </p> * * @author Werner Randelshofer * @version $Id$ */ public class ExportFileAction extends AbstractViewAction { private static final long serialVersionUID = 1L; public static final String ID = "file.export"; private Component oldFocusOwner; private boolean proposeFileName; /** Creates a new instance. */ public ExportFileAction(Application app, @Nullable View view) { this(app, view, false); } public ExportFileAction(Application app, @Nullable View view, boolean proposeFileName) { super(app, view); ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.app.Labels"); labels.configureAction(this, ID); this.proposeFileName = proposeFileName; } /** Whether the export file action shall propose a file name or shall * leave the filename empty. * @return True if filename is proposed. */ public boolean isProposeFileName() { return proposeFileName; } /** Whether the export file action shall propose a file name or shall * leave the filename empty. * * @param newValue True if filename shall be proposed. */ public void setProposeFileName(boolean newValue) { this.proposeFileName = newValue; } @Override public void actionPerformed(ActionEvent evt) { final View view = getActiveView(); if (view.isEnabled()) { ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.app.Labels"); oldFocusOwner = SwingUtilities.getWindowAncestor(view.getComponent()).getFocusOwner(); view.setEnabled(false); try { URIChooser fileChooser = getApplication().getExportChooser(view); if (proposeFileName) { // => try to propose file name without extension URI proposedURI = view.getURI(); if (proposedURI != null) { try { URI selectedURI = fileChooser.getSelectedURI(); File selectedFolder; if (selectedURI == null) { Preferences prefs = Preferences.userNodeForPackage(getApplication().getModel().getClass()); try { selectedURI = new URI(// prefs.get("recentExportFile", new File(proposedURI).getParentFile().toURI().toString())// ); selectedFolder = new File(selectedURI).getParentFile(); } catch (URISyntaxException ex) { // selectedURI is null selectedFolder = new File(proposedURI).getParentFile(); } } else { selectedFolder = new File(selectedURI).getParentFile(); } File file = new File(selectedFolder,new File(proposedURI).getName()); String name = file.getName(); int p = name.lastIndexOf('.'); if (p != -1) { name = name.substring(0, p); file = new File(selectedFolder, name); proposedURI = file.toURI(); } } catch (IllegalArgumentException e) { } } fileChooser.setSelectedURI(proposedURI); } JSheet.showSheet(fileChooser, view.getComponent(), labels.getString("filechooser.export"), new SheetListener() { @Override public void optionSelected(final SheetEvent evt) { if (evt.getOption() == JFileChooser.APPROVE_OPTION) { URI uri = evt.getChooser().getSelectedURI(); if ((evt.getChooser() instanceof JFileURIChooser) && evt.getFileChooser().getFileFilter() instanceof ExtensionFileFilter) { uri = ((ExtensionFileFilter) evt.getFileChooser().getFileFilter()).makeAcceptable(evt.getFileChooser().getSelectedFile()).toURI(); } else { uri = evt.getChooser().getSelectedURI(); } Preferences prefs = Preferences.userNodeForPackage(getApplication().getModel().getClass()); prefs.put("recentExportFile", uri.toString()); if (evt.getChooser() instanceof JFileURIChooser) { exportView(view, uri, evt.getChooser()); } else { exportView(view, uri, null); } } else { view.setEnabled(true); if (oldFocusOwner != null) { oldFocusOwner.requestFocus(); } } } }); } catch (Error err) { view.setEnabled(true); throw err; } catch (Throwable err) { view.setEnabled(true); err.printStackTrace(); } } } protected void exportView(final View view, final URI uri, @Nullable final URIChooser chooser) { view.execute(new BackgroundTask() { @Override protected void construct() throws IOException { view.write(uri, chooser); } @Override protected void failed(Throwable value) { System.out.flush(); value.printStackTrace(); // FIXME localize this error messsage JSheet.showMessageSheet(view.getComponent(), "<html>" + UIManager.getString("OptionPane.css") + "<b>Couldn't export to the file \"" + URIUtil.getName(uri) + "\".<p>" + "Reason: " + value, JOptionPane.ERROR_MESSAGE); } @Override protected void finished() { view.setEnabled(true); SwingUtilities.getWindowAncestor(view.getComponent()).toFront(); if (oldFocusOwner != null) { oldFocusOwner.requestFocus(); } } }); } }