Package org.alastairmailer

Source Code of org.alastairmailer.PDFHandler

package org.alastairmailer;

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingWorker;

import org.apache.lucene.document.Document;
import org.apache.pdfbox.searchengine.lucene.LucenePDFDocument;
import org.jpedal.PdfDecoder;
import org.jpedal.exception.PdfException;
import org.jpedal.objects.PdfPageData;

public class PDFHandler extends FiletypeHandler {

  public static final ImageIcon PDF_ICON_SMALL = new ImageIcon(LuceneSidePanelPlugin.getResourceURL("images/pdf-icon-small.png"));
  public static final ImageIcon PDF_ICON_LARGE = new ImageIcon(LuceneSidePanelPlugin.getResourceURL("images/pdf-icon-large.png"));
  public static final ImageIcon UP_ICON = new ImageIcon(LuceneSidePanelPlugin.getResourceURL("images/up.png"));
  public static final ImageIcon DOWN_ICON = new ImageIcon(LuceneSidePanelPlugin.getResourceURL("images/down.png"));
  public static final ImageIcon PAGEUP_ICON = new ImageIcon(LuceneSidePanelPlugin.getResourceURL("images/page-up.png"));
  public static final ImageIcon PAGEDOWN_ICON = new ImageIcon(LuceneSidePanelPlugin.getResourceURL("images/page-down.png"));
  public static final ImageIcon ZOOMIN_ICON = new ImageIcon(LuceneSidePanelPlugin.getResourceURL("images/zoom-in.png"));
  public static final ImageIcon ZOOMOUT_ICON = new ImageIcon(LuceneSidePanelPlugin.getResourceURL("images/zoom-out.png"));

  public Icon getIcon() {
    return PDFHandler.PDF_ICON_SMALL;
  }
   
  @Override
  public boolean accept(File dir, String name) {
    return name.endsWith(".pdf");
  }

  @Override
  protected Document getDocument(File f) throws IOException {
    Logger pdfBox = Logger.getLogger("org.apache.pdfbox.util.PDFStreamEngine");
    pdfBox.setLevel(Level.WARNING);
    Document doc = LucenePDFDocument.getDocument(f);
    return doc;
  }

  public String getUID(File f) {
    return f.getAbsolutePath() + File.separator + f.lastModified();
  }
   
  @Override
  public void cache(File f, String[] terms) {
    super.cache(f, terms);
    cacher.requestCache(f, 1, terms);
  }

  @Override
  public void decache(File f) {
    super.decache(f);
    cacher.decache(f);
  }

  public PDFHandler() {
    super();
    PdfDecoder.init(true);
    contextPanel = buildPanel();
    cacher = new PDFImageCacher();
  }
 
  private JPanel contextPanel;
 
  public JPanel getButtonBar() {
    JPanel buttonBar = new JPanel();
    buttonBar.setLayout(new BoxLayout(buttonBar, BoxLayout.LINE_AXIS));
    buttonBar.add(Box.createHorizontalGlue());
    upButton = new JButton(UP_ICON);
    upButton.setEnabled(false);
    upButton.setToolTipText("Previous match");
    buttonBar.add(upButton);
    downButton = new JButton(DOWN_ICON);
    downButton.setEnabled(false);
    downButton.setToolTipText("Next match");
    buttonBar.add(downButton);
    buttonBar.add(Box.createHorizontalStrut(20 + 10));
    pageUpButton = new JButton(PAGEUP_ICON);
    pageUpButton.setEnabled(false);
    pageUpButton.setToolTipText("Previous page");
    buttonBar.add(pageUpButton);
    pageDownButton = new JButton(PAGEDOWN_ICON);
    pageDownButton.setEnabled(false);
    pageDownButton.setToolTipText("Next page");
    buttonBar.add(pageDownButton);
    buttonBar.add(Box.createHorizontalStrut(20 + 10));
    openPDFButton = new JButton(PDF_ICON_LARGE);
    openPDFButton.setToolTipText("Open PDF in external viewer");
    if (Desktop.isDesktopSupported() == false) {
      openPDFButton.setEnabled(false);
    }
    buttonBar.add(openPDFButton);
    buttonBar.add(Box.createHorizontalGlue());
    setListeners();
    return buttonBar;
  }
 
  private JPanel buildPanel() {
    JPanel p = new JPanel();
    GridBagLayout gBagPDF = new GridBagLayout();
    GridBagConstraints cPDF = new GridBagConstraints();
    p.setLayout(gBagPDF);
    cPDF.gridx = 0;
    cPDF.gridy = 0;
    cPDF.weightx = 0.9;
    cPDF.weighty = 0.5;
    cPDF.fill = GridBagConstraints.BOTH;
    scroll = new JScrollPane();
    scroll.setViewportView(pdfLabel);
    scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    scroll.getVerticalScrollBar().setUnitIncrement(10);
    scroll.getHorizontalScrollBar().setUnitIncrement(10);
    p.add(scroll, cPDF);
    return p;
  }
 
  private void setListeners() {
   
    pageDownButton.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {
        currentDoc.showNextPage();
      }
     
    });
    pageUpButton.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {
        currentDoc.showPreviousPage();
      }
     
    });
    openPDFButton.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {
          SwingWorker<Object, Object> openExternal = new SwingWorker<Object, Object>() {

            @Override
            protected Object doInBackground() throws Exception {
              Desktop.getDesktop().open(currentFile);
              return null;
            }
            @Override
            protected void done() {
              super.done();
              contextPanel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
          };
          contextPanel.setCursor(new Cursor(Cursor.WAIT_CURSOR));
          openExternal.execute();
      }
     
    });
    downButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        currentDoc.showNextMatch();
      }
    });
    upButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        currentDoc.showPreviousMatch();
      }
    });

  }
  private JScrollPane scroll;
  private void centreRectangle(Rectangle h) {
    JViewport view = scroll.getViewport();
    int centreX = (int)Math.round(h.getCenterX() - view.getViewRect().width / 2.0);
    int centreY = (int)Math.round(h.getCenterY() - view.getViewRect().height / 2.0);
    view.setViewPosition(new Point(centreX, centreY));
  }
  @Override
  public Component getContextComponent() {
    return contextPanel;
  }
 
  private JLabel pdfLabel = new JLabel();
  private float zoom = 1.5f;
  private JButton pageUpButton;
  private JButton pageDownButton;
  private PDFImageCacher cacher;
  private File currentFile;
 
  private String[] search;
  private JButton openPDFButton;
  private JButton upButton;
  private JButton downButton;
 
  class PDFDocument extends SwingWorker<List<PageRectangle>, PDFHighlightImage> {

    private File loadFile;
    private PDFImageCacher imageCache;
    private PdfPageData metadata;
    private Rectangle selectedMatch;
    private int currentPage = -10;
    private int currentMatch = -1;
   
    public PDFDocument(File f, PDFImageCacher cache, String[] searchTerms) throws PdfException {
      super();
      loadFile = f;
      imageCache = cache;
      PdfDecoder d = new PdfDecoder(false);
      d.openPdfFile(loadFile.toString());
      metadata = d.getPdfPageData();
      for (int i = 1; i <= metadata.getPageCount(); i++) {
        imageCache.requestCache(loadFile, i, searchTerms);
      }
    }
   
    public void load() {
      pdfLabel = new JLabel("Loading...", JLabel.CENTER);
      pdfLabel.setBackground(Color.white);
      scroll.getViewport().setBackground(Color.white);
      pagePanel.add(pdfLabel);
      scroll.setViewportView(pdfLabel);
      contextPanel.revalidate();
      execute();
    }
   
    private PDFHighlightImage firstMatchImage = null;

    @Override
    protected List<PageRectangle> doInBackground() throws Exception {
      boolean firstMatchFound = false;
      List<PageRectangle> allHighlights = new Vector<PageRectangle>();
     
      for (int i = 1; i <= metadata.getPageCount(); i++) {
        PDFHighlightImage im = imageCache.getImage(currentFile, i);
        for (Rectangle r: im.highlights) {
          allHighlights.add(new PageRectangle(r, i));
        }
        if (allHighlights.size() != 0 && !firstMatchFound) {
          firstMatchFound = true;
          firstMatchImage = im;
        }
        publish(im);
      }
      return allHighlights;
    }
   
    private List<PDFHighlightImage> pages = new Vector<PDFHighlightImage>();
    private Map<Rectangle, Integer> matchPages = new HashMap<Rectangle, Integer>();
    private List<Rectangle> matches = new Vector<Rectangle>();
   
    @Override
    protected void process(List<PDFHighlightImage> chunks) {
      for (PDFHighlightImage page : chunks) {
        pages.add(page);
        for (Rectangle r : page.highlights) {
          matches.add(r);
          matchPages.put(r, page.pageNum);
        }
        if (page == firstMatchImage) {
          selectedMatch = firstMatchImage.highlights.get(0);
          currentMatch = 0;
          currentPage = firstMatchImage.pageNum;
          showPage(currentPage);
          centreRectangle(selectedMatch);

        } else {
          updateButtons();
        }

      }
     
    }
   
    private final Color selectColor = new Color(255,255,0,125);
    private final Color otherColor = new Color(0,0,255,125);
    private JPanel pagePanel = new JPanel();
    public void showPage(int n) {
      if (n > 0 && n <= pages.size()) {
        currentPage = n;
        pagePanel.removeAll();
        pagePanel.setBackground(Color.DARK_GRAY);
        scroll.getViewport().setBackground(Color.DARK_GRAY);
        BufferedImage im = pages.get(n - 1).pdfImage;
        Graphics2D g = im.createGraphics();
        g.scale(zoom, zoom);
        pdfLabel = new JLabel(new ImageIcon(pages.get(n - 1).pdfImage));
        pagePanel.add(pdfLabel);
        pdfLabel.setLayout(null);
        for (Rectangle r : pages.get(n - 1).highlights) {
          JLabel highlight = new JLabel();
          highlight.setBackground(r == selectedMatch ? selectColor : otherColor);
          pdfLabel.add(highlight);
          highlight.setBounds(r);
          highlight.setCursor(new Cursor(Cursor.HAND_CURSOR));
          highlight.setOpaque(true);
          final Rectangle rRef = r;
          final int rRefPage = n;
          highlight.addMouseListener(new MouseListener() {

            public void mouseClicked(MouseEvent e) {
              selectedMatch = rRef;
              currentMatch = matches.indexOf(rRef);
              updateButtons();
              Point oldView = scroll.getViewport().getViewPosition();
              showPage(rRefPage);
              scroll.getViewport().setViewPosition(oldView);
            }

            public void mouseEntered(MouseEvent e) { }

            public void mouseExited(MouseEvent e) { }

            public void mousePressed(MouseEvent e) { }

            public void mouseReleased(MouseEvent e) { }
           
          });
        }
        scroll.setViewportView(pagePanel);

        contextPanel.revalidate();
      }
      updateButtons();
    }
   
    private void updateButtons() {
      pageDownButton.setEnabled(currentPage < pages.size());
      pageUpButton.setEnabled(currentPage > 1);
      downButton.setEnabled(currentMatch < matches.size());
      upButton.setEnabled(currentMatch > 1);     
    }

    public void showNextPage() {
      showPage(currentPage + 1);
    }
   
    public void showPreviousPage() {
      showPage(currentPage - 1);
    }
   
    public void showMatch(int n) {
      if (n >= 0 && n < matches.size()) {
        selectedMatch = matches.get(n);
        currentMatch = n;
        int selectedMatchPage = matchPages.get(selectedMatch);
        showPage(selectedMatchPage);
        centreRectangle(selectedMatch);
      }
      downButton.setEnabled(n < matches.size() - 1);
      upButton.setEnabled(n > 0);
    }
   
    public void showNextMatch() {
      showMatch(currentMatch + 1);
    }
   
    public void showPreviousMatch() {
      showMatch(currentMatch - 1);
    }
  }
 
  private PDFDocument currentDoc;
 
  public void showContext(File f, String searchQ) {
    try {
      search = searchQ.split(" ");
      if (currentFile != null) {
        cacher.decacheExceptFirst(currentFile);
      }
      currentFile = f;
      currentDoc = new PDFDocument(currentFile, cacher, search);
      currentDoc.load();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  @Override
  protected void doStart() throws Exception { }

  @Override
  protected void doStop() throws Exception { }

}

class PageRectangle {
 
  public final Rectangle r;
  public final int page;
 
  public PageRectangle(Rectangle r, int page) {
    this.r = r;
    this.page = page;
  }
}
TOP

Related Classes of org.alastairmailer.PDFHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.