
import ch.randelshofer.pdf.EmbedPDFApplet;

/*
 * @(#)EmbedPDFApplet.java  1.0  2008-09-18
 * 
 * Copyright (c) 2008 Werner Randelshofer
 * Hausmatt 10, Immensee, CH-6405, Switzerland.
 * All rights reserved.
 * 
 * The copyright of this software is owned by Werner Randelshofer. 
 * You may not use, copy or modify this software, except in  
 * accordance with the license agreement you entered into with  
 * Werner Randelshofer. For details see accompanying license terms
 */
import ch.randelshofer.util.Applets;
import com.sun.pdfview.PDFFile;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.List;
import javax.swing.*;
import org.jhotdraw.gui.Worker;

/**
 * A Swing-based applet that displays a PDF file.
 *
 * @author Werner Randelshofer, Hausmatt 10, CH-6405 Immensee
 * @version 1.0 September 18, 2008 Created.
 */
public class EmbedPDF extends EmbedPDFApplet {

    private class Handler implements DropTargetListener {

        /**
         * Called when a drag operation has
         * encountered the <code>DropTarget</code>.
         * <P>
         * @param dtde the <code>DropTargetDragEvent</code>
         */
        public void dragEnter(DropTargetDragEvent event) {
            if (event.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                event.acceptDrag(DnDConstants.ACTION_COPY);
            } else {
                event.rejectDrag();
            }
        }

        /**
         * The drag operation has departed
         * the <code>DropTarget</code> without dropping.
         * <P>
         * @param dte the <code>DropTargetEvent</code>
         */
        public void dragExit(DropTargetEvent event) {
            // Nothing to do
        }

        /**
         * Called when a drag operation is ongoing
         * on the <code>DropTarget</code>.
         * <P>
         * @param dtde the <code>DropTargetDragEvent</code>
         */
        public void dragOver(DropTargetDragEvent event) {
            if (event.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                event.acceptDrag(DnDConstants.ACTION_COPY);
            } else {
                event.rejectDrag();
            }
        }

        /**
         * The drag operation has terminated
         * with a drop on this <code>DropTarget</code>.
         * This method is responsible for undertaking
         * the transfer of the data associated with the
         * gesture. The <code>DropTargetDropEvent</code>
         * provides a means to obtain a <code>Transferable</code>
         * object that represents the data object(s) to
         * be transfered.<P>
         * From this method, the <code>DropTargetListener</code>
         * shall accept or reject the drop via the
         * acceptDrop(int dropAction) or rejectDrop() methods of the
         * <code>DropTargetDropEvent</code> parameter.
         * <P>
         * Subsequent to acceptDrop(), but not before,
         * <code>DropTargetDropEvent</code>'s getTransferable()
         * method may be invoked, and data transfer may be
         * performed via the returned <code>Transferable</code>'s
         * getTransferData() method.
         * <P>
         * At the completion of a drop, an implementation
         * of this method is required to signal the success/failure
         * of the drop by passing an appropriate
         * <code>boolean</code> to the <code>DropTargetDropEvent</code>'s
         * dropComplete(boolean success) method.
         * <P>
         * Note: The actual processing of the data transfer is not
         * required to finish before this method returns. It may be
         * deferred until later.
         * <P>
         * @param dtde the <code>DropTargetDropEvent</code>
         */
        public void drop(DropTargetDropEvent event) {
            if (event.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                event.acceptDrop(DnDConstants.ACTION_COPY);

                try {
                    List<File> files = (List<File>) event.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
                    if (files.size() >= 1) {
                        for (File f : files) {
                            String lcName = f.getName().toLowerCase();
                            if (lcName.endsWith(".pdf")) {
                                loadFile(f);
                                break;
                            }
                        }
                    }
                } catch (IOException e) {
                    JOptionPane.showConfirmDialog(
                            EmbedPDF.this,
                            "Could not access the dropped data.",
                            "EmbedPDF: Drop Failed",
                            JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE);
                } catch (UnsupportedFlavorException e) {
                    JOptionPane.showConfirmDialog(
                            EmbedPDF.this,
                            "Unsupported data flavor.",
                            "EmbedPDF: Drop Failed",
                            JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE);
                }
            } else {
                event.rejectDrop();
            }
        }

        /**
         * Called if the user has modified
         * the current drop gesture.
         * <P>
         * @param dtde the <code>DropTargetDragEvent</code>
         */
        public void dropActionChanged(DropTargetDragEvent event) {
            // Nothing to do
        }
    }

    private void loadFile(final File file) {
        try {
            pdfURL = file.toURI().toURL();
        } catch (MalformedURLException e) {
            // This should never happen
            e.printStackTrace();
            return;
        }
        setGlassPane(progressView);
        progressView.setVisible(true);
        new Worker<PDFFile>() {

            protected PDFFile construct() throws Exception {
                return readPDF(pdfURL, progressView);
            }

            @Override
            protected void done(PDFFile value) {
                Frame frame = (Frame) SwingUtilities.getWindowAncestor(EmbedPDF.this);
                frame.setTitle("EmbedPDF: " + file.getName());
                pdfDocumentPanel.setPDF(value);
            }

            @Override
            protected void failed(Throwable error) {
                error.printStackTrace();
                Frame frame = (Frame) SwingUtilities.getWindowAncestor(EmbedPDF.this);
                frame.setTitle("EmbedPDF");
                pdfDocumentPanel.setPDF(null);
            }

            @Override
            protected void finished() {
                progressView.setVisible(false);
            }
        }.start();
    }

    @Override
    protected void installDropTargets() {
        Handler handler = new Handler();
        new DropTarget(this, handler);
    }

    public static void main(final String[] args) {
        System.setProperty("apple.laf.useScreenMenuBar", "true");


        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                final JFrame f = new JFrame("EmbedPDF");
                final EmbedPDF applet = new EmbedPDF();
                Applets.setMainArgs(applet, args);

                f.add(applet);
                f.setSize(400, 600);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
                SwingUtilities.invokeLater(new Runnable() {public void run() {
                applet.init();}});
                SwingUtilities.invokeLater(new Runnable() {public void run() {
                applet.start();}});

                JMenuBar mb = new JMenuBar();
                JMenu m = new JMenu("File");
                mb.add(m);
                JMenuItem mi = new JMenuItem("Open...");
                m.add(mi);
                mi.addActionListener(new ActionListener() {

                    private FileDialog fd;

                    public void actionPerformed(ActionEvent e) {
                        if (fd == null) {
                            fd = new FileDialog(f);
                            fd.setMode(FileDialog.LOAD);
                        }

                        fd.setVisible(true);
                        if (fd.getFile() != null) {
                            applet.loadFile(new File(fd.getDirectory(), fd.getFile()));
                        }
                    }
                });
                f.setJMenuBar(mb);
            }
        });
    }
    /** This method is called from within the init() method to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     * /
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
    }// </editor-fold>//GEN-END:initComponents
     */
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
}
