Package de.chris_soft.utilities.swing.pdf

Source Code of de.chris_soft.utilities.swing.pdf.PdfThumbnailList

/**
* NanoDoA - File based document archive
*
* Copyright (C) 2011-2012 Christian Packenius, christian.packenius@googlemail.com
*
* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*/
package de.chris_soft.utilities.swing.pdf;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionListener;

import de.chris_soft.utilities.LogUtils;
import de.chris_soft.utilities.pdf.PdfPageRenderUtility;
import de.chris_soft.utilities.swing.SwingUtils;

/**
* Swing list that displays thumbnails of the pages of a PDF file.
* @author Christian Packenius.
*/
public class PdfThumbnailList implements ListCellRenderer, Runnable {
  private final JScrollPane scrollPane = new JScrollPane();

  private final int iconSize;

  private final List<Image> thumbnailList = new ArrayList<Image>();

  private final List<JLabel> labelList = new ArrayList<JLabel>();

  final DefaultListModel model = new DefaultListModel();

  private final JList jList = new JList(model);

  private volatile PdfPageRenderUtility pdfRenderer;

  int pageCount;

  private final Color backgroundColor = new JLabel().getBackground();

  private final BufferedImage notLoadedIcon;

  private final BufferedImage errorIcon;

  /**
   * Constructor.
   * @param iconSize Size of the icons (N*N).
   */
  public PdfThumbnailList(int iconSize) {
    this.iconSize = iconSize;
    notLoadedIcon = new BufferedImage(iconSize, iconSize, BufferedImage.TYPE_INT_ARGB);
    errorIcon = new BufferedImage(iconSize, iconSize, BufferedImage.TYPE_INT_ARGB);
    createDefaultImageIcon(notLoadedIcon);
    createDefaultImageIcon(errorIcon);
    jList.setPrototypeCellValue(notLoadedIcon);
    jList.setCellRenderer(this);
    jList.setBackground(backgroundColor);
    scrollPane.setViewportView(jList);
    scrollPane.setPreferredSize(new Dimension(iconSize + 25, 0));
  }

  private void createDefaultImageIcon(BufferedImage image) {
    Graphics2D g2d = (Graphics2D) image.getGraphics();
    g2d.setBackground(Color.LIGHT_GRAY);
    g2d.setColor(Color.LIGHT_GRAY);
    g2d.fillRect(0, 0, iconSize, iconSize);
    if (image == errorIcon) {
      g2d.setColor(Color.RED);
      g2d.setBackground(Color.RED);
      g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
      g2d.drawLine(iconSize / 5, iconSize / 5, iconSize - 1 - iconSize / 5, iconSize - 1 - iconSize / 5);
      g2d.drawLine(iconSize - 1 - iconSize / 5, iconSize / 5, iconSize / 5, iconSize - 1 - iconSize / 5);
      g2d.dispose();
      g2d.setColor(Color.GRAY);
      g2d.setBackground(Color.GRAY);
      g2d.setStroke(new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
      g2d.drawLine(iconSize / 5, iconSize / 5, iconSize - 1 - iconSize / 5, iconSize - 1 - iconSize / 5);
      g2d.drawLine(iconSize - 1 - iconSize / 5, iconSize / 5, iconSize / 5, iconSize - 1 - iconSize / 5);
      g2d.dispose();
    }
  }

  /**
   * Test method.
   * @param args Not used.
   * @throws IOException
   */
  public static void main(String[] args) throws IOException {
    JFrame frame = new JFrame();
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(BorderLayout.CENTER, new JLabel("adsf"));
    PdfThumbnailList ptl = new PdfThumbnailList(128);
    frame.getContentPane().add(BorderLayout.WEST, ptl.getComponent());
    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    frame.setExtendedState(Frame.MAXIMIZED_BOTH);
    frame.setVisible(true);
    ptl.setPdfFile(new PdfPageRenderUtility(new File("1-3262-7391-9387.pdf")));
  }

  /**
   * Returns the swing component for this PDF thumbnail list.
   * @return JScrollPane object.
   */
  public JScrollPane getComponent() {
    return scrollPane;
  }

  /**
   * Adds a PDF file to the view list.
   * @param pdfRenderer PDF file to add in the list.
   */
  public void setPdfFile(PdfPageRenderUtility pdfRenderer) {
    if (pdfRenderer != null && this.pdfRenderer != pdfRenderer) {
      this.pdfRenderer = pdfRenderer;

      Thread thread = new Thread(this, "PDF thumbnail list thread");
      thread.setDaemon(true);
      thread.start();
    }
  }

  /**
   * Adds a selection listener to the pdf list.
   * @param listener Selection listener.
   */
  public void addListSelectionListener(ListSelectionListener listener) {
    jList.addListSelectionListener(listener);
  }

  /**
   * Returns the current selected page in the PDF page list.
   * @return Selected page index (1..N).
   */
  public int getSelectedPage() {
    int index = jList.getSelectedIndex();
    if (index >= 0) {
      index++;
    }
    return index;
  }

  /**
   * @see javax.swing.ListCellRenderer#getListCellRendererComponent(javax.swing.JList,
   *      java.lang.Object, int, boolean, boolean)
   */
  @Override
  public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
      boolean cellHasFocus) {
    int pageID = -1;
    String errorText = null;
    if (value instanceof String) {
      try {
        pageID = Integer.parseInt((String) value);
      }
      catch (NumberFormatException nfe) {
        errorText = (String) value;
      }
    }
    Image image = getImageForRendering(pageID);
    String text = getTextForRendering(pageID);
    JLabel label = createLabelForThumbnailList(isSelected, image, errorText == null ? text : errorText);
    labelList.add(index, label);
    return label;
  }

  private Image getImageForRendering(int pageID) {
    if (pageID <= 0 || pageID > thumbnailList.size()) {
      return notLoadedIcon;
    }
    return thumbnailList.get(pageID - 1);
  }

  private String getTextForRendering(int pageID) {
    if (pageID <= 0) {
      return "Loading...";
    }
    if (pageID > thumbnailList.size()) {
      return "Loading page " + pageID + "...";
    }
    if (thumbnailList.get(pageID - 1) == null) {
      return "Cannot load page " + pageID;
    }
    return "Page " + pageID;
  }

  private JLabel createLabelForThumbnailList(boolean isSelected, Image image, String text) {
    JLabel label = new JLabel();
    label.setHorizontalAlignment(SwingConstants.CENTER);
    if (image != null) {
      label.setIcon(new ImageIcon(image));
    }
    if (text != null) {
      label.setText(text);
    }
    if (text != null && image != null) {
      label.setVerticalTextPosition(SwingConstants.BOTTOM);
      label.setHorizontalTextPosition(SwingConstants.CENTER);
    }
    if (isSelected) {
      boolean hasFocus = jList.hasFocus();
      if (hasFocus) {
        label.setBorder(new LineBorder(Color.DARK_GRAY, 3));
      }
      else {
        label.setBorder(new LineBorder(Color.LIGHT_GRAY, 3));
      }
    }
    else {
      label.setBorder(new LineBorder(backgroundColor, 3));
    }
    return label;
  }

  /**
   * Set a page as selected.
   * @param pageID Page to select (1..N).
   */
  public void setSelectedPage(final int pageID) {
    if (pageID - 1 != jList.getSelectedIndex()) {
      try {
        SwingUtils.runInGuiNow(new Runnable() {
          @Override
          public void run() {
            try {
              changeSelectedPdfPage(pageID);
            }
            catch (Exception exception) {
              LogUtils.log(exception);
            }
          }
        });
      }
      catch (Exception exception) {
        LogUtils.log(exception);
      }
    }
  }

  void changeSelectedPdfPage(final int pageID) {
    try {
      if (pageID <= model.getSize() && pageID > 0) {
        jList.setSelectedIndex(pageID - 1);
        jList.ensureIndexIsVisible(pageID - 1);
      }
    }
    catch (Exception e) {
      LogUtils.log(e);
    }
  }

  /**
   * @see java.lang.Runnable#run()
   */
  @Override
  public void run() {
    synchronized (this) {
      File pdfFile2view = initRenderingOfNewPdfFile();

      for (int i = 1; i <= pageCount; i++) {
        if (!pdfFile2view.equals(pdfRenderer.pdfFile)) {
          break;
        }
        renderAndDisplaySingleImage(i);
      }
    }
  }

  private File initRenderingOfNewPdfFile() {
    File pdfFile2view = pdfRenderer.pdfFile;
    thumbnailList.clear();
    pageCount = 0;
    try {
      pageCount = pdfRenderer.pageCount;

      SwingUtils.runInGuiNow(new Runnable() {
        @Override
        public void run() {
          model.removeAllElements();
          // model.setSize(pageCount);
        }
      });
      for (int i = 1; i <= pageCount; i++) {
        if (!pdfFile2view.equals(pdfRenderer.pdfFile)) {
          break;
        }
        final int pageID = i;
        SwingUtils.runInGuiNow(new Runnable() {
          @Override
          public void run() {
            // if (model.getSize() > pageID) {
            // model.setElementAt("" + pageID, pageID);
            // }
            // else {
            model.addElement("" + pageID);
            // }
          }
        });
        if (pageID == 1) {
          setSelectedPage(1);
        }
      }
    }
    catch (Exception exception) {
      LogUtils.log(exception);
    }
    return pdfFile2view;
  }

  private void renderAndDisplaySingleImage(int i) {
    final int k = i;
    String text = "" + k;
    try {
      Image image = pdfRenderer.getPage(i, iconSize);
      thumbnailList.add(image);
    }
    catch (Exception exception) {
      try {
        if (thumbnailList.size() < i) {
          thumbnailList.add(errorIcon);
        }
        text = "Cannot load page " + i + ".";
      }
      catch (Exception e) {
        // An error occurs only if an image change has happend!
        // LogUtils.log(e);
      }
    }
    finally {
      repaintListItem(k, text);
    }
  }

  private void repaintListItem(final int k, final String text) {
    try {
      SwingUtils.runInGuiNow(new Runnable() {
        @Override
        public void run() {
          // MUST be a new string object!
          model.set(k - 1, new String(text));
        }
      });
    }
    catch (Exception exception) {
      // An error occurs only if an image change has happend!
      // LogUtils.log(e);
    }
  }
}
TOP

Related Classes of de.chris_soft.utilities.swing.pdf.PdfThumbnailList

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.