package cz.cuni.mff.peckam.java.origamist.gui.common; import java.awt.Component; import java.awt.Cursor; import java.awt.FlowLayout; import java.awt.HeadlessException; import java.awt.event.ActionEvent; import java.io.File; import java.text.MessageFormat; import java.util.List; import java.util.ResourceBundle; import java.util.Set; import java.util.concurrent.ExecutionException; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JProgressBar; import javax.swing.KeyStroke; import javax.swing.SwingWorker; import javax.swing.filechooser.FileNameExtensionFilter; import org.apache.log4j.Logger; import cz.cuni.mff.peckam.java.origamist.model.Origami; import cz.cuni.mff.peckam.java.origamist.services.ServiceLocator; import cz.cuni.mff.peckam.java.origamist.services.TooltipFactory; import cz.cuni.mff.peckam.java.origamist.services.interfaces.ConfigurationManager; import cz.cuni.mff.peckam.java.origamist.services.interfaces.OrigamiHandler; import cz.cuni.mff.peckam.java.origamist.utils.ExportFormat; import cz.cuni.mff.peckam.java.origamist.utils.ExportOptions; /** * Exports the currently displayed origami to the given format. * * @author Martin Pecka */ public class ExportAction extends AbstractAction { /** */ private static final long serialVersionUID = -399462365929673938L; /** The format to export to. */ protected ExportFormat format; /** The origami to export. */ protected Origami origami; /** * @param format The format to export to. */ public ExportAction(Origami origami, ExportFormat format) { this.format = format; this.origami = origami; } @Override public void actionPerformed(final ActionEvent e) { beforeAction(e); final ResourceBundle appMessages = ResourceBundle.getBundle("application", ServiceLocator.get(ConfigurationManager.class).get().getLocale()); final Component parent; if (e.getSource() instanceof Component) parent = (Component) e.getSource(); else parent = null; JFileChooser chooser = new JFileChooser(); File defaultFile = ServiceLocator.get(ConfigurationManager.class).get().getLastExportPath().getParentFile(); chooser.setCurrentDirectory(defaultFile); chooser.setFileFilter(new FileNameExtensionFilter("*." + format.toString().toLowerCase(), format.toString())); chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); chooser.setDialogType(JFileChooser.SAVE_DIALOG); chooser.setApproveButtonText(appMessages.getString("exportDialog.approve")); chooser.setApproveButtonMnemonic(KeyStroke.getKeyStroke(appMessages.getString("exportDialog.approve.mnemonic")) .getKeyCode()); chooser.setApproveButtonToolTipText(ServiceLocator.get(TooltipFactory.class).getDecorated( appMessages.getString("exportDialog.approve.tooltip.message"), appMessages.getString("exportDialog.approve.tooltip.title"), "save.png", KeyStroke.getKeyStroke("alt " + appMessages.getString("exportDialog.approve.mnemonic")))); if (chooser.showDialog(parent, null) == JFileChooser.APPROVE_OPTION) { chooserApproved(e); File f = chooser.getSelectedFile(); if (!chooser.accept(f)) { f = new File(f.toString() + "." + format.toString().toLowerCase()); } ServiceLocator.get(ConfigurationManager.class).get().setLastExportPath(f); if (f.exists()) { if (JOptionPane.showConfirmDialog(parent, MessageFormat.format(appMessages.getString("exportDialog.overwrite"), new Object[] { f }), appMessages.getString("exportDialog.overwrite.title"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null) != JOptionPane.YES_OPTION) { return; } } final File file = f; final ExportOptions options = format.askForOptions(origami); final JDialog progressDialog = new JDialog(); final JProgressBar bar = new JProgressBar(0, format.getNumOfProgressChunks(origami, options)); bar.setStringPainted(true); bar.setString(appMessages.getString("exporting.no.percentage")); progressDialog.getContentPane().setLayout(new FlowLayout()); progressDialog.setUndecorated(true); progressDialog.setAlwaysOnTop(true); progressDialog.setLocationRelativeTo(null); final SwingWorker<Set<File>, Void> worker = new SwingWorker<Set<File>, Void>() { private int chunksReceived = 0; @Override protected Set<File> doInBackground() throws Exception { final Runnable progressCallback = new Runnable() { @Override public void run() { publish(new Void[] { null }); if (isCancelled()) throw new RuntimeException(); } }; return ServiceLocator.get(OrigamiHandler.class).export(origami, file, format, options, progressCallback); } @Override protected void process(List<Void> chunks) { chunksReceived += chunks.size(); bar.setValue(chunksReceived); bar.setString(MessageFormat.format(appMessages.getString("exporting.percentage"), bar.getPercentComplete())); } @Override protected void done() { progressDialog.setVisible(false); progressDialog.dispose(); try { if (!isCancelled()) { Set<File> resultFiles = get(); StringBuilder b = new StringBuilder(); for (File f : resultFiles) b.append("\n").append(f.toString()); JOptionPane.showMessageDialog(parent, MessageFormat.format( appMessages.getString("exportSuccessful.message"), new Object[] { b.toString(), resultFiles.size() }), appMessages.getString("exportSuccessful.title"), JOptionPane.INFORMATION_MESSAGE, null); } } catch (HeadlessException e) { JOptionPane.showMessageDialog(parent, MessageFormat.format( appMessages.getString("failedToExport.message"), new Object[] { file.toString() }), appMessages.getString("failedToExport.title"), JOptionPane.ERROR_MESSAGE, null); Logger.getLogger("application").warn("Unable to export origami.", e); } catch (InterruptedException e) { JOptionPane.showMessageDialog(parent, MessageFormat.format( appMessages.getString("failedToExport.message"), new Object[] { file.toString() }), appMessages.getString("failedToExport.title"), JOptionPane.ERROR_MESSAGE, null); Logger.getLogger("application").warn("Unable to export origami.", e); } catch (ExecutionException e) { JOptionPane.showMessageDialog(parent, MessageFormat.format( appMessages.getString("failedToExport.message"), new Object[] { file.toString() }), appMessages.getString("failedToExport.title"), JOptionPane.ERROR_MESSAGE, null); Logger.getLogger("application").warn("Unable to export origami.", e); } ExportAction.this.done(e); } }; progressDialog.getContentPane().add(bar); JButton cancel = new JButton(); cancel.setAction(new AbstractAction() { /** */ private static final long serialVersionUID = 104733262578076493L; @Override public void actionPerformed(ActionEvent e) { worker.cancel(true); } }); cancel.setText(appMessages.getString("buttons.cancel")); progressDialog.getContentPane().add(cancel); progressDialog.pack(); progressDialog.setVisible(true); worker.execute(); } else { if (e.getSource() instanceof JComponent) ((JComponent) e.getSource()).setCursor(Cursor.getDefaultCursor()); } } /** * This method gets called before any action from this action is taken. */ protected void beforeAction(ActionEvent evt) { } /** * This method gets called when the user approves the file chooser dialog. */ protected void chooserApproved(ActionEvent evt) { } /** * This method gets called when the export action has been done. */ protected void done(ActionEvent evt) { } }