/*
* @(#)SaveFileAction.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 javax.annotation.Nullable;
import org.jhotdraw.gui.filechooser.ExtensionFileFilter;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.URI;
import org.jhotdraw.app.*;
import org.jhotdraw.app.action.AbstractViewAction;
import org.jhotdraw.util.*;
import org.jhotdraw.gui.*;
import org.jhotdraw.gui.URIChooser;
import org.jhotdraw.gui.JFileURIChooser;
import org.jhotdraw.gui.event.*;
import org.jhotdraw.net.URIUtil;
/**
* Saves the changes in the active view. If the active view has not an URI,
* an {@code URIChooser} is presented.
* <p>
* This action is called when the user selects the Save item in the File
* menu. The menu item is automatically created by the application.
* <p>
* If you want this behavior in your application, you have to create it
* and put it in your {@code ApplicationModel} in method
* {@link ApplicationModel#initApplication}.
* <hr>
* <b>Features</b>
*
* <p><em>Allow multiple views per URI</em><br>
* When the feature is disabled, {@code SaveFileAction} prevents saving to
* an URI which is opened in another view.<br>
* See {@link org.jhotdraw.app} for a description of the feature.
* </p>
*
* <p><em>Open last URI on launch</em><br>
* {@code SaveFileAction} supplies data for this feature by calling
* {@link Application#addRecentURI} when it successfully saved a file.
* See {@link org.jhotdraw.app} for a description of the feature.
* </p>
*
* @author Werner Randelshofer
* @version $Id$
*/
public class SaveFileAction extends AbstractViewAction {
private static final long serialVersionUID = 1L;
public static final String ID = "file.save";
private boolean saveAs;
private Component oldFocusOwner;
/** Creates a new instance. */
public SaveFileAction(Application app, @Nullable View view) {
this(app, view, false);
}
/** Creates a new instance. */
public SaveFileAction(Application app, @Nullable View view, boolean saveAs) {
super(app, view);
this.saveAs = saveAs;
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.app.Labels");
labels.configureAction(this, ID);
}
protected URIChooser getChooser(View view) {
URIChooser chsr = (URIChooser) (view.getComponent()).getClientProperty("saveChooser");
if (chsr == null) {
chsr = getApplication().getModel().createSaveChooser(getApplication(), view);
view.getComponent().putClientProperty("saveChooser", chsr);
}
return chsr;
}
@Override
public void actionPerformed(ActionEvent evt) {
final View view = getActiveView();
if (view == null) {
return;
}
if (view.isEnabled()) {
oldFocusOwner = SwingUtilities.getWindowAncestor(view.getComponent()).getFocusOwner();
view.setEnabled(false);
if (!saveAs && view.getURI() != null && view.canSaveTo(view.getURI())) {
saveViewToURI(view, view.getURI(), null);
} else {
URIChooser fileChooser = getChooser(view);
JSheet.showSaveSheet(fileChooser, view.getComponent(), new SheetListener() {
@Override
public void optionSelected(final SheetEvent evt) {
if (evt.getOption() == JFileChooser.APPROVE_OPTION) {
final URI uri;
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();
}
// Prevent same URI from being opened more than once
if (!getApplication().getModel().isAllowMultipleViewsPerURI()) {
for (View v : getApplication().getViews()) {
if (v != view && v.getURI() != null && v.getURI().equals(uri)) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.app.Labels");
JSheet.showMessageSheet(view.getComponent(), labels.getFormatted("file.saveAs.couldntSaveIntoOpenFile.message", evt.getFileChooser().getSelectedFile().getName()));
view.setEnabled(true);
return;
}
}
}
saveViewToURI(view, uri, evt.getChooser());
} else {
view.setEnabled(true);
if (oldFocusOwner != null) {
oldFocusOwner.requestFocus();
}
}
}
});
}
}
}
protected void saveViewToURI(final View view, final URI file,
@Nullable final URIChooser chooser) {
view.execute(new BackgroundTask() {
@Override
protected void construct() throws IOException {
view.write(file, chooser);
}
@Override
protected void done() {
view.setURI(file);
view.markChangesAsSaved();
int multiOpenId = 1;
for (View p : view.getApplication().views()) {
if (p != view && p.getURI() != null && p.getURI().equals(file)) {
multiOpenId = Math.max(multiOpenId, p.getMultipleOpenId() + 1);
}
}
getApplication().addRecentURI(file);
view.setMultipleOpenId(multiOpenId);
}
@Override
protected void failed(Throwable value) {
value.printStackTrace();
String message = value.getMessage() != null ? value.getMessage() : value.toString();
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.app.Labels");
JSheet.showMessageSheet(getActiveView().getComponent(),
"<html>" + UIManager.getString("OptionPane.css")
+ "<b>" + labels.getFormatted("file.save.couldntSave.message", URIUtil.getName(file)) + "</b><p>"
+ ((message == null) ? "" : message),
JOptionPane.ERROR_MESSAGE);
}
@Override
protected void finished() {
view.setEnabled(true);
SwingUtilities.getWindowAncestor(view.getComponent()).toFront();
if (oldFocusOwner != null) {
oldFocusOwner.requestFocus();
}
}
});
}
}