/***
* Copyright (c) 2008, Endless Loop Software, Inc.
*
* This file is part of EgoNet.
*
* EgoNet 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
* (at your option) any later version.
*
* EgoNet 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 org.egonet.util;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import java.awt.print.Pageable;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.net.URL;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PagePreview extends JDialog implements ActionListener
{
private final static double DEFAULT_ZOOM_FACTOR_STEP = 0.5;
private JLabel pageNum = new JLabel("Page #1");
private JButton print;
protected Pageable pageable;
public PagePreview(String title, JFrame owner, Pageable pageable, double zoom)
{
super(owner, title, true);
this.pageable = pageable;
Preview preview = new Preview(pageable, pageNum, zoom);
JScrollPane scrollPane = new JScrollPane(preview);
JToolBar toolbar = new JToolBar();
print = getButton("Print", "print.gif", null);
print.addActionListener(this);
JButton close = new JButton("Close");
close.addActionListener(this);
getContentPane().add(scrollPane, "Center");
//toolbar.setRollover(true);
getContentPane().add(toolbar, "North");
toolbar.add(getButton("Back24.gif", new BrowseAction(preview, -1)));
toolbar.add(getButton("Forward24.gif", new BrowseAction(preview, 1)));
toolbar.add(new JToolBar.Separator());
toolbar.add(getButton("ZoomIn24.gif", new ZoomAction(preview, DEFAULT_ZOOM_FACTOR_STEP)));
toolbar.add(getButton("ZoomOut24.gif", new ZoomAction(preview, -DEFAULT_ZOOM_FACTOR_STEP)));
toolbar.add(new JToolBar.Separator());
toolbar.add(print);
toolbar.add(close);
JPanel dialog = new JPanel();
dialog.setLayout(new FlowLayout(FlowLayout.CENTER));
dialog.add(pageNum);
getContentPane().add(dialog, "South");
this.pack();
}
public PagePreview(String title, JFrame owner, Pageable pageable)
{
this(title, owner, pageable, 0.0);
}
public PagePreview(String title, JFrame owner, Printable printable, PageFormat format, int pages, double zoom)
{
this(title, owner, new MyPageable(printable, format, pages), zoom);
}
public PagePreview(String title, JFrame owner, Printable printable, PageFormat format, int pages)
{
this(title, owner, printable, format, pages, 0.0);
}
private static class MyPageable implements Pageable
{
public MyPageable(Printable printable, PageFormat format, int pages)
{
this.printable = printable;
this.format = format;
this.pages = pages;
}
public int getNumberOfPages()
{
return pages;
}
public Printable getPrintable(int index)
{
if (index >= pages)
throw new IndexOutOfBoundsException();
return printable;
}
public PageFormat getPageFormat(int index)
{
if (index >= pages)
throw new IndexOutOfBoundsException();
return format;
}
private Printable printable;
private PageFormat format;
private int pages;
}
public JButton getButton(String iconName)
{
return getButton(null, iconName, null);
}
private JButton getButton(String iconName, AbstractAction action)
{
return getButton(null, iconName, action);
}
private JButton getButton(String name, String iconName, AbstractAction action)
{
JButton result = null;
ImageIcon icon = null;
URL imageURL = PagePreview.class.getResource(iconName);
if (imageURL != null) icon = new ImageIcon(imageURL);
if (action != null)
{
if (icon != null) action.putValue(Action.SMALL_ICON, new ImageIcon(imageURL));
if (name != null) action.putValue(Action.NAME, name);
result = new JButton(action);
}
else result = new JButton(name, icon);
return result;
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == print)
{
final PrinterJob prnJob = PrinterJob.getPrinterJob();
PageFormat pf = pageable.getPageFormat(0);
prnJob.setPrintable(pageable.getPrintable(0), pf);
if (!prnJob.printDialog()) return;
Thread runner = new Thread()
{
public void run()
{
try
{
prnJob.print();
}
catch (PrinterException ex)
{
System.err.println("Printing error: " + ex.toString());
throw new RuntimeException(ex);
}
}
};
runner.start();
}
dispose();
}
}
class Preview extends JComponent
{
final private static Logger logger = LoggerFactory.getLogger(Preview.class);
protected Pageable pageable;
protected int index = 0;
protected double zoom = 0.0;
protected JLabel pageNum;
private final static int DEFAULT_PREVIEW_SIZE = 300;
private final static double MINIMUM_ZOOM_FACTOR = 0.1;
public Preview(Pageable pageable, JLabel pageNum, double zoom)
{
this.pageable = pageable;
this.pageNum = pageNum;
PageFormat format = pageable.getPageFormat(index);
if (zoom == 0.0)
{
if (format.getOrientation() == PageFormat.PORTRAIT)
{
this.zoom = DEFAULT_PREVIEW_SIZE / format.getHeight();
}
else
{
this.zoom = DEFAULT_PREVIEW_SIZE / format.getWidth();
}
}
else this.zoom = zoom;
resize();
}
protected void paintPaper(Graphics g, PageFormat format)
{
g.setColor(Color.white);
g.fillRect(0, 0, (int) format.getWidth(), (int) format.getHeight());
g.setColor(Color.black);
g.drawRect(0, 0, (int) format.getWidth() - 1, (int) format.getHeight() - 1);
}
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.scale(zoom, zoom);
try
{
PageFormat format = pageable.getPageFormat(index);
Printable printable = pageable.getPrintable(index);
pageNum.setText("Page " + (index + 1) + " of " + pageable.getNumberOfPages());
paintPaper(g, format);
printable.print(g, format, index);
}
catch (PrinterException ex)
{
logger.error(ex.toString());
}
catch (IndexOutOfBoundsException ex)
{
logger.error(ex.toString());
}
}
public void moveIndex(int indexStep)
{
int newIndex = index + indexStep;
try
{
pageable.getPrintable(newIndex);
resize();
index = newIndex;
}
catch (IndexOutOfBoundsException ignored)
{
ignored.printStackTrace();
}
}
public void changeZoom(double zoom)
{
this.zoom = Math.max(MINIMUM_ZOOM_FACTOR, this.zoom + zoom);
resize();
}
public void resize()
{
PageFormat format = pageable.getPageFormat(index);
int size = (int) Math.max(format.getWidth() * zoom, format.getHeight() * zoom);
setPreferredSize(new Dimension(size, size));
revalidate();
}
public Dimension getMinimumSize()
{
return getPreferredSize();
}
}
class BrowseAction extends AbstractAction
{
protected Preview preview;
protected int pageStep;
public BrowseAction(Preview preview, int pageStep)
{
super();
this.preview = preview;
this.pageStep = pageStep;
}
public void actionPerformed(ActionEvent e)
{
preview.moveIndex(pageStep);
preview.repaint();
}
}
class ZoomAction extends AbstractAction
{
protected Preview preview;
protected double zoomStep;
public ZoomAction(Preview preview, double zoomStep)
{
super();
this.preview = preview;
this.zoomStep = zoomStep;
}
public void actionPerformed(ActionEvent e)
{
preview.changeZoom(zoomStep);
preview.repaint();
}
}