net.sf.jhylafax.SendDialog.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.jhylafax.SendDialog.java

Source

/**
 * JHylaFax - A java client for HylaFAX.
 *
 * Copyright (C) 2005 by Steffen Pingel <steffenp@gmx.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package net.sf.jhylafax;

import static net.sf.jhylafax.JHylaFAX.i18n;
import gnu.hylafax.HylaFAXClient;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.swing.Action;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import net.sf.jhylafax.fax.FaxCover;
import net.sf.jhylafax.fax.FaxJob;
import net.sf.jhylafax.fax.HylaFAXClientHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xnap.commons.gui.Builder;
import org.xnap.commons.gui.Dialogs;
import org.xnap.commons.gui.ErrorDialog;
import org.xnap.commons.gui.FileChooserPanel;
import org.xnap.commons.gui.action.AbstractXNapAction;
import org.xnap.commons.io.Job;
import org.xnap.commons.io.ProgressMonitor;
import org.xnap.commons.io.SubTaskProgressMonitor;
import org.xnap.commons.io.UserAbortException;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * A dialog for sending faxes.
 * 
 * @author Steffen Pingel
 */
public class SendDialog extends AbstractFaxDialog {

    private final static Log logger = LogFactory.getLog(AbstractQueuePanel.class);

    private JLabel documentLabel;
    private JPanel coverPanel;
    private JTextField coverSenderTextField;
    private JLabel coverSenderLabel;
    private JTextField coverRecepientTextField;
    private JLabel coverRecepientLabel;
    private JTextField coverSubjectTextField;
    private JLabel coverSubjectLabel;
    private JTextArea coverCommentTextArea;
    private JLabel coverCommentLabel;
    private JPanel documentPanel;
    private DefaultFormBuilder documentPanelBuilder;
    private List<FileChooserPanel> documentFileChooserPanels;
    private JCheckBox includeCoverCheckBox;
    private JLabel includeCoverLabel;
    private JScrollPane coverCommentScrollPane;
    private PreviewCoverAction previewCoverAction;

    private MoreDocumentsAction moreDocumentsAction;

    private boolean quitAfterSending;

    public SendDialog(JFrame owner) {
        super(owner);

        moreDocumentsAction = new MoreDocumentsAction();
        previewCoverAction = new PreviewCoverAction();

        addNumberTextField();

        addDocumentsPanel();

        builder.append("", Builder.createButton(moreDocumentsAction));
        builder.nextLine();

        addDateControls();

        includeCoverCheckBox = new JCheckBox();
        includeCoverLabel = builder.append("", includeCoverCheckBox);
        builder.nextLine();

        initializeCoverPanel();
        coverPanel.setVisible(false);
        previewCoverAction.setEnabled(false);
        includeCoverCheckBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                coverPanel.setVisible(includeCoverCheckBox.isSelected());
                previewCoverAction.setEnabled(includeCoverCheckBox.isSelected());
                pack();
            }
        });

        getButtonPanel().add(Builder.createButton(previewCoverAction), 0);

        FaxJob job = new FaxJob();
        HylaFAXClientHelper.initializeFromSettings(job);
        setJob(job);

        updateLabels();
        pack();
    }

    private void addDocumentsPanel() {
        documentFileChooserPanels = new ArrayList<FileChooserPanel>();

        FormLayout layout = new FormLayout("left:max(40dlu;pref), 3dlu, pref:grow", "");
        documentPanelBuilder = new DefaultFormBuilder(layout);
        FileChooserPanel documentFileChooserPanel = new MyFileChooserPanel(DEFAULT_COLUMNS);
        documentFileChooserPanel.getFileChooser().setMultiSelectionEnabled(true);
        documentFileChooserPanels.add(documentFileChooserPanel);
        documentLabel = documentPanelBuilder.append("", documentFileChooserPanel);

        this.builder.appendRow(builder.getLineGapSpec());
        this.builder.nextLine();
        this.builder.appendRow("fill:pref:grow");
        this.builder.append(documentPanelBuilder.getPanel(), 6);

        builder.nextLine();
    }

    private void initializeCoverPanel() {
        FormLayout layout = new FormLayout("left:max(40dlu;pref), 3dlu, pref:grow", "");
        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
        coverPanel = builder.getPanel();
        this.builder.appendRow(builder.getLineGapSpec());
        this.builder.nextLine();
        this.builder.appendRow("fill:pref:grow");
        this.builder.append(coverPanel, 6);

        coverSenderTextField = new JTextField(DEFAULT_COLUMNS);
        coverSenderTextField.setText(Settings.FULLNAME.getValue());
        coverSenderLabel = builder.append("", coverSenderTextField);
        builder.nextLine();

        coverRecepientTextField = new JTextField(DEFAULT_COLUMNS);
        coverRecepientLabel = builder.append("", coverRecepientTextField);
        builder.nextLine();

        coverSubjectTextField = new JTextField(DEFAULT_COLUMNS);
        coverSubjectLabel = builder.append("", coverSubjectTextField);
        builder.nextLine();

        coverCommentTextArea = new JTextArea(3, DEFAULT_COLUMNS);
        coverCommentLabel = builder.append("");
        builder.appendRow("fill:pref:grow"); // second row for text area
        CellConstraints cc = new CellConstraints();
        coverCommentScrollPane = new JScrollPane(coverCommentTextArea);
        builder.add(coverCommentScrollPane, cc.xywh(builder.getColumn(), builder.getRow(), 1, 2));
        builder.nextLine(2);
    }

    @Override
    public boolean apply() {
        if (!super.apply()) {
            return false;
        }

        if (!includeCoverCheckBox.isSelected()) {
            boolean filenameProvided = false;
            for (FileChooserPanel documentFileChooserPanel : documentFileChooserPanels) {
                if (documentFileChooserPanel.getTextField().getText().trim().length() != 0) {
                    filenameProvided = true;
                    if (Settings.CONFIRM_NONPS.getValue()) {
                        if (!checkPostScript(documentFileChooserPanel.getTextField().getText())) {
                            documentFileChooserPanel.getTextField().requestFocus();
                            return false;
                        }
                    }
                }
            }
            if (!filenameProvided) {
                Dialogs.showError(this, i18n.tr("You must at least send a document or a cover"),
                        i18n.tr("JHylaFAX Error"));
                documentFileChooserPanels.get(0).getTextField().requestFocus();
                return false;
            }
        }

        Fax fax = createFax();
        if (fax != null) {
            if (send(fax)) {
                if (quitAfterSending) {
                    JHylaFAX.getInstance().exit();
                }
                return true;
            }
        }

        return false;
    }

    private boolean checkPostScript(String filename) {
        try {
            if (!HylaFAXClientHelper.isPostscript(filename)) {
                if (Dialogs.showConfirmDialog(this,
                        i18n.tr("Do you really want to send the non PostScript file \"{0}\"?", filename),
                        i18n.tr("JHylaFAX - Send non PostScript file"), JOptionPane.YES_NO_OPTION,
                        Settings.CONFIRM_NONPS) == JOptionPane.NO_OPTION) {
                    return false;
                }
            }
        } catch (IOException e) {
            logger.debug("Error checking for PostScript", e);
            ErrorDialog.showError(this, i18n.tr("Could not check for PostScript"), i18n.tr("JHylaFAX Error"), e);
            return false;
        }
        return true;
    }

    private Fax createFax() {
        Fax fax = new Fax();

        for (FileChooserPanel documentFileChooserPanel : documentFileChooserPanels) {
            String filename = documentFileChooserPanel.getTextField().getText();
            if (filename.trim().length() > 0) {
                File file = new File(filename);
                fax.documents.add(file);
            }
        }

        if (includeCoverCheckBox.isSelected() && !createFaxCover(fax)) {
            return null;
        }

        return fax;
    }

    private boolean createFaxCover(Fax fax) {
        if (fax == null) {
            throw new IllegalArgumentException("value may not be null");
        }

        String filename;
        if (Settings.USE_INTERNAL_COVER.getValue()) {
            filename = "faxcover.ps";
            fax.coverIn = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
        } else {
            filename = Settings.COVER_PATH.getValue();
            try {
                fax.coverIn = new FileInputStream(filename);
            } catch (FileNotFoundException e) {
                fax.coverIn = null;
            }
        }
        if (fax.coverIn == null) {
            Dialogs.showError(this, i18n.tr("Could not read cover file: {0}", filename), i18n.tr("JHylaFAX Error"));
            return false;
        }

        fax.cover = new FaxCover(Settings.PAPER.getValue());
        fax.cover.from = coverSenderTextField.getText();
        fax.cover.to = coverRecepientTextField.getText();
        fax.cover.regarding = coverSubjectTextField.getText();
        fax.cover.comments = coverCommentTextArea.getText();
        fax.cover.todays_date = SimpleDateFormat.getDateTimeInstance().format(new Date());
        for (Iterator<File> it = fax.documents.iterator(); it.hasNext();) {
            fax.cover.addDocument(it.next().getAbsolutePath());
        }

        return true;
    }

    private boolean send(final Fax fax) {
        Job<?> ioJob = new Job() {
            public Object run(ProgressMonitor monitor) throws Exception {
                monitor.setTotalSteps(13 + fax.documents.size() * 10);

                HylaFAXClient client = JHylaFAX.getInstance().getConnection(monitor);
                monitor.work(1);

                client.mode(HylaFAXClient.MODE_STREAM);
                client.type(HylaFAXClient.TYPE_IMAGE);

                String serverCoverFilename = null;
                if (fax.cover != null && fax.coverIn != null) {
                    monitor.setText(i18n.tr("Generating cover"));
                    SubTaskProgressMonitor coverMonitor = new SubTaskProgressMonitor(monitor, 5, 0);
                    StringBuffer data = fax.cover.generate(fax.coverIn, coverMonitor);
                    coverMonitor.done();

                    // Cover senden
                    byte[] buffer = data.toString().getBytes(FaxCover.CHARSET);
                    TransferMonitor transferMonitor = new TransferMonitor(monitor, 5, buffer.length);
                    client.addTransferListener(transferMonitor);
                    InputStream in = new ByteArrayInputStream(buffer);
                    try {
                        serverCoverFilename = client.putTemporary(in);
                    } finally {
                        transferMonitor.transferCompleted();
                        client.removeTransferListener(transferMonitor);
                        in.close();
                    }
                    // check if monitor was cancelled
                    monitor.work(0);
                } else {
                    monitor.work(10);
                }

                monitor.setText(i18n.tr("Uploading documents"));
                List<String> serverFilenames = new ArrayList<String>();
                for (File file : fax.documents) {
                    TransferMonitor transferMonitor = new TransferMonitor(monitor, 10, file.length());
                    client.addTransferListener(transferMonitor);
                    InputStream in = new BufferedInputStream(new FileInputStream(file));
                    try {
                        serverFilenames.add(client.putTemporary(in));
                    } finally {
                        transferMonitor.transferCompleted();
                        client.removeTransferListener(transferMonitor);
                        in.close();
                    }
                    // check if monitor was cancelled
                    monitor.work(0);
                }

                gnu.hylafax.Job sendJob = client.createJob();
                HylaFAXClientHelper.applyParameter(sendJob, getJob());
                if (serverCoverFilename != null) {
                    if (Settings.SEND_COVER_AS_DOCUMENT.getValue()) {
                        sendJob.addDocument(serverCoverFilename);
                    } else {
                        sendJob.setProperty("COVER ", serverCoverFilename);
                    }
                }
                for (String filename : serverFilenames) {
                    sendJob.addDocument(filename);
                }
                monitor.work(1);

                client.submit(sendJob);
                monitor.work(1);

                return null;
            }
        };

        try {
            JHylaFAX.getInstance().runJob(SendDialog.this, ioJob);
            JHylaFAX.getInstance().updateTables();
        } catch (UserAbortException e) {
            return false;
        } catch (Exception e) {
            logger.debug("Error sending fax", e);
            ErrorDialog.showError(this, i18n.tr("Could not send fax"), i18n.tr("JHylaFAX Error"), e);
            return false;
        }
        return true;
    }

    private File saveCover(final Fax fax) {
        if (fax.cover == null || fax.coverIn == null) {
            throw new IllegalArgumentException("fax.cover and fax.coverIn must not be null");
        }

        Job<File> ioJob = new Job<File>() {
            public File run(ProgressMonitor monitor) throws Exception {
                monitor.setTotalSteps(10);

                monitor.setText(i18n.tr("Generating cover"));
                SubTaskProgressMonitor coverMonitor = new SubTaskProgressMonitor(monitor, 5, 0);
                StringBuffer data = fax.cover.generate(fax.coverIn, coverMonitor);
                coverMonitor.done();

                File outputFile = File.createTempFile("jhylafax", ".ps");
                outputFile.deleteOnExit();
                OutputStream out = new FileOutputStream(outputFile);
                monitor.setText(i18n.tr("Saving cover"));
                try {
                    out.write(data.toString().getBytes(FaxCover.CHARSET));
                } finally {
                    out.close();
                }
                monitor.work(5);

                return outputFile;
            }
        };

        try {
            return JHylaFAX.getInstance().runJob(SendDialog.this, ioJob);
        } catch (UserAbortException e) {
            return null;
        } catch (Exception e) {
            logger.debug("Error previewing cover", e);
            ErrorDialog.showError(this, i18n.tr("Could not preview cover"), i18n.tr("JHylaFAX Error"), e);
            return null;
        }
    }

    public void updateLabels() {
        super.updateLabels();

        setTitle(i18n.tr("Send Fax"));
        documentLabel.setText(i18n.tr("Document"));
        includeCoverLabel.setText(i18n.tr("Include Cover"));
        coverSenderLabel.setText(i18n.tr("Sender"));
        coverRecepientLabel.setText(i18n.tr("Recepient"));
        coverSubjectLabel.setText(i18n.tr("Subject"));
        coverCommentLabel.setText(i18n.tr("Comment"));

        previewCoverAction.updateLabels();
        moreDocumentsAction.updateLabels();
    }

    public void setDocument(String document) {
        documentFileChooserPanels.get(0).getTextField().setText(document);
    }

    /**
     * A container used for parameter passing.  
     */
    private class Fax {
        FaxCover cover;
        InputStream coverIn;
        List<File> documents = new ArrayList<File>();
    }

    private class PreviewCoverAction extends AbstractXNapAction implements LocaleChangeListener {

        public PreviewCoverAction() {
            //putValue(ICON_FILENAME, "configure.png");
        }

        public void actionPerformed(ActionEvent event) {
            if (!includeCoverCheckBox.isSelected()) {
                throw new IllegalStateException("Cover page is not enabled");
            }

            String viewerPath = JHylaFAXHelper.getViewerPath("docq");
            if (viewerPath == null) {
                return;
            }

            Fax fax = createFax();
            if (fax == null) {
                return;
            }

            File tempFile = saveCover(fax);
            if (tempFile != null) {
                JHylaFAXHelper.view(viewerPath, new File[] { tempFile });
            }
        }

        public void updateLabels() {
            putValue(Action.NAME, i18n.tr("Preview Cover"));
            putValue(Action.SHORT_DESCRIPTION, i18n.tr("Opens an external programm to preview the cover page"));
        }

    }

    private class MoreDocumentsAction extends AbstractXNapAction implements LocaleChangeListener {

        public MoreDocumentsAction() {
        }

        public void actionPerformed(ActionEvent event) {
            FileChooserPanel documentFileChooserPanel = addDocumentFileChooser();
            documentFileChooserPanel.getTextField().requestFocus();
        }

        public void updateLabels() {
            putValue(Action.NAME, i18n.tr("More"));
            putValue(Action.SHORT_DESCRIPTION,
                    i18n.tr("Displays an additional field to enter a document filename"));
        }

    }

    private class MyFileChooserPanel extends FileChooserPanel {

        public MyFileChooserPanel(int columns) {
            super(columns);
        }

        @Override
        protected void fileSelected(File file) {
            File[] files = getFileChooser().getSelectedFiles();
            if (files != null && files.length > 1) {
                // files[0] equals file and is handled by the panel
                for (int i = 1; i < files.length; i++) {
                    // add a new panel for all other files
                    FileChooserPanel chooser = addDocumentFileChooser();
                    chooser.setFile(files[i]);
                }
            }
            // reset selection
            getFileChooser().setSelectedFiles(null);
        }

    }

    protected FileChooserPanel addDocumentFileChooser() {
        FileChooserPanel documentFileChooserPanel = new MyFileChooserPanel(DEFAULT_COLUMNS);
        documentFileChooserPanel.setFileChooser(documentFileChooserPanels.get(0).getFileChooser());
        documentFileChooserPanels.add(documentFileChooserPanel);
        documentPanelBuilder.append("", documentFileChooserPanel);
        documentPanelBuilder.nextLine();
        pack();
        return documentFileChooserPanel;
    }

    public void addDocument(String filename) {
        FileChooserPanel panel = addDocumentFileChooser();
        panel.getTextField().setText(filename);
    }

    public void setQuitAfterSending(boolean quitAfterSending) {
        this.quitAfterSending = quitAfterSending;
    }

}