📄 printpreviewdialog.java
字号:
/*
* 11/14/2003
*
* PrintPreviewDialog.java - A dialog showing the user what their Printable
* print job will look like.
* Copyright (C) 2003 Robert Futrell
* email@address.com
* www.website.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 2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.fife.print;
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.net.URLClassLoader;
import java.util.ResourceBundle;
import javax.imageio.ImageIO;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
import org.fife.ui.RButton;
import org.fife.ui.RScrollPane;
import org.fife.ui.StatusBar;
/**
* A dialog showing the user what their print job will look like.
*
* @author Robert Futrell
* @version 0.7
*/
public class PrintPreviewDialog extends JDialog implements ActionListener, ItemListener {
/**
*
*/
private static final long serialVersionUID = -1819939201971582203L;
private JPanel previewPanel; // The panel that actually shows the preview.
private PagePreview[] pageImage; // Image of the page.
private Printable masterImage; // The "master" (full-sized) image.
private JButton printButton;
private JButton nextPageButton; // Button to view the next page.
private JButton prevPageButton; // Button to view the previous page.
private JButton closeButton;
private JComboBox sizeComboBox; // To choose the preview's size.
private JComboBox numPagesComboBox; // To choose the number of pages to view at a time.
private int scale; // Current scale of pages, in percent (i.e., 10 ==> 10%).
private int pageWidth;
private int pageHeight;
private int currentPage; // The first currently visible page.
private int numVisiblePages; // Number of visible pages.
private int numPages; // Number of pages in the document.
private Cursor zoomInCursor;
private Cursor zoomOutCursor;
private Border pagePreviewBorder; // Shared to reduce footprint.
private PageFormat pageFormat; // Used when generating a page.
private static final int MAX_PAGE_COUNT = 4;
/*****************************************************************************/
/**
* Creates a new <code>PrintPreviewDialog</code>.
*
* @param owner The application from which you are going to print.
* @param printable The component you are going to print.
*/
public PrintPreviewDialog(Frame owner, Printable printable) {
super(owner);
ResourceBundle msg = ResourceBundle.getBundle(
"org.fife.print.PrintPreviewDialog");
// Get the page format to use when generating a preview image.
PrinterJob prnJob = PrinterJob.getPrinterJob();
pageFormat = prnJob.defaultPage();
createCursors();
JPanel toolBarPanel = new JPanel();
toolBarPanel.setLayout(new GridLayout(1,6, 5,10));
JPanel topPanel = new JPanel();
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS));
topPanel.add(toolBarPanel);
topPanel.add(Box.createHorizontalGlue());
topPanel.setBorder(BorderFactory.createEmptyBorder(1,1,2,1));
JPanel contentPane = new JPanel(new BorderLayout());
setContentPane(contentPane);
contentPane.add(topPanel, BorderLayout.NORTH);
contentPane.add(new StatusBar(""), BorderLayout.SOUTH);
printButton = new RButton(msg.getString("Print"));
printButton.setActionCommand("Print");
printButton.addActionListener(this);
toolBarPanel.add(printButton);
prevPageButton = new RButton(msg.getString("PrevPage"));
prevPageButton.setEnabled(false);
prevPageButton.setActionCommand("PrevPage");
prevPageButton.addActionListener(this);
toolBarPanel.add(prevPageButton);
nextPageButton = new RButton(msg.getString("NextPage"));
nextPageButton.setActionCommand("NextPage");
nextPageButton.addActionListener(this);
toolBarPanel.add(nextPageButton);
closeButton = new RButton(msg.getString("Close"));
closeButton.setActionCommand("Close");
closeButton.addActionListener(this);
toolBarPanel.add(closeButton);
sizeComboBox = new JComboBox(
new String[] { "10%", "25%", "33%", "50%", "66%",
"75%", "100%", "150%", "200%" }
);
sizeComboBox.addItemListener(this);
toolBarPanel.add(sizeComboBox);
numPagesComboBox = new JComboBox(
new String[] { "1", "2", "3", "4" } );
numPagesComboBox.addItemListener(this);
toolBarPanel.add(numPagesComboBox);
toolBarPanel.add(Box.createHorizontalGlue());
previewPanel = new JPanel();
previewPanel.setBackground(Color.GRAY);
RScrollPane scrollPane = new RScrollPane(previewPanel);
contentPane.add(scrollPane);
this.masterImage = printable;
scale = 25;
sizeComboBox.setSelectedItem("25%");
pageImage = new PagePreview[MAX_PAGE_COUNT];
setNumVisiblePages(1); // Only one page is visible initially.
setPreviewPage(0); // Initially preview the first page.
setModal(true); // So the user can't switch back to RText.
// Calculate the number of pages in the document.
// NOTE: There MUST be a more efficient way to do this...
JDialog dummyDialog = new JDialog();
dummyDialog.pack();
Graphics h = dummyDialog.getGraphics();
numPages = 0;
try {
while (printable.print(h, pageFormat, numPages) == Printable.PAGE_EXISTS)
numPages++;
} catch (PrinterException pe) { pe.printStackTrace(); }
h.dispose();
// Get ready to go!
updateButtons();
setTitle(msg.getString("Title"));
pack();
}
/*****************************************************************************/
public void actionPerformed(ActionEvent e) {
String actionCommand = e.getActionCommand();
if (actionCommand.equals("Close")) {
setVisible(false);
}
else if (actionCommand.equals("NextPage")) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
incrementPreviewPage();
} finally { // To ensure GUI stays correct.
updateButtons();
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
else if (actionCommand.equals("PrevPage")) {
setCursor( Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
decrementPreviewPage();
} finally { // To ensure GUI stays correct.
updateButtons();
setCursor( Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
// If the user elects to print the document, close the Print Preview dialog.
// (The printing is done by the other listener).
else if (actionCommand.equals("Print")) {
// Try to print!
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
PrintRequestAttributeSet attributeSet = new HashPrintRequestAttributeSet();
attributeSet.add(new Copies(1));
attributeSet.add(Sides.ONE_SIDED);
attributeSet.add(OrientationRequested.PORTRAIT);
PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, null);//attributeSet);
PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
//DocFlavor[] flavors = defaultService.getSupportedDocFlavors();
PrintService chosenService = ServiceUI.printDialog(null, 200, 200, services, defaultService,
flavor, attributeSet);
if (chosenService != null) {
DocPrintJob job = chosenService.createPrintJob();
Doc myDoc = new SimpleDoc(masterImage, flavor, null);//attributeSet);
try {
job.print(myDoc, attributeSet);
} catch (PrintException pe) {
JOptionPane.showMessageDialog(null, "Error attempting to print: "+pe+".",
"Printing Error", JOptionPane.ERROR_MESSAGE);
}
}
// After we've printed (or not), hide the Print Preview dialog.
setVisible(false);
}
}
/*****************************************************************************/
/**
* Creates the custom zoom in/zoom out cursors.
*/
private void createCursors() {
// Get the zoom in/zoom out cursor images.
BufferedImage zoomInCursor1 = null;
BufferedImage zoomOutCursor1 = null;
URLClassLoader cl = (URLClassLoader)this.getClass().getClassLoader();
try {
zoomInCursor1 = ImageIO.read(cl.findResource("org/fife/print/images/zoomin.gif"));
zoomOutCursor1 = ImageIO.read(cl.findResource("org/fife/print/images/zoomout.gif"));
} catch (Exception e) { // IOException or MalformedURLException.
e.printStackTrace();
Cursor defaultCursor = Cursor.getPredefinedCursor(
Cursor.DEFAULT_CURSOR);
zoomInCursor = defaultCursor;
zoomOutCursor = defaultCursor;
return;
}
Point hotspot = new Point(0,0);
zoomInCursor = getCustomCursor(zoomInCursor1, hotspot,
"ZoomInCursor", 32,32);
zoomOutCursor = getCustomCursor(zoomOutCursor1, hotspot,
"ZoomOutCursor", 32,32);
}
/*****************************************************************************/
/**
* Decrements the first preview page, if possible, and updates the
* screen. This method is designed as an alternative to
* <code>setPreviewPage()</code> that performs better with the more
* preview pages visible, as only one new page ever has to be created.
*/
public void decrementPreviewPage() {
if (pageImage==null || currentPage==0)
return;
currentPage--;
// Move 'backward' one page in all visible pages. This should
// should work even if some of the pages are null (i.e., no
// more pages to view), as we'd just be setting stuff to null.
// We'll reuse the last page preview to keep from having to
// create a new image, etc.
PagePreview pp = null;
pp = pageImage[numVisiblePages-1];
previewPanel.remove(pp);
for (int i=numVisiblePages-1; i>0; i--)
pageImage[i] = pageImage[i-1];
pageImage[0] = null; // May help GC.
pageWidth = (int)(pageFormat.getWidth());
pageHeight = (int)(pageFormat.getHeight());
try {
BufferedImage tempImage = pp.getSourceImage();
Graphics g = tempImage.getGraphics();
g.setColor(Color.white);
g.fillRect(0,0, pageWidth,pageHeight);
if (masterImage.print(g, pageFormat, currentPage) == Printable.PAGE_EXISTS) {
int w = (int)(pageWidth*scale/100);
int h = (int)(pageHeight*scale/100);
pp.setScaledSize(w,h); // Recreate scaled version.
pageImage[0] = pp;
previewPanel.add(pp, 0);
}
else {
pageImage[0] = null;
}
g.dispose();
} catch (PrinterException pe) {
pe.printStackTrace();
}
previewPanel.revalidate();
previewPanel.repaint(); // Needed, but why?
}
/*****************************************************************************/
/**
* Returns the text on the "Close" button.
*
* @return The text on the Close button.
* @see #setCloseButtonText
*/
public final String getCloseButtonText() {
return closeButton.getText();
}
/*****************************************************************************/
/**
* Returns the cursor to use for a print-preview page of the specified
* scale.
*
* @param scale The scale of the page, in percent.
* @return The cursor to display while over the page.
*/
private final Cursor getCursorForScale(int scale) {
return scale>=100 ? zoomOutCursor : zoomInCursor;
}
/*****************************************************************************/
/**
* Creates and returns a cursor using the specified image and
* properties.
*
* @param image The image to use for the cursor.
* @param hotspot The "hotspot" for the cursor (i.e., when you click,
* this is the exact pixel whose location is "clicked").
* @param name A name for the cursor.
* @param preferredWidth The desired width of the cursor. Note that
* this is only a suggestion; the cursor returned will be whatever
* width and height the system says it wants.
* @param preferredHeight The desired height of the cursor. Like
* <code>preferredWidth</code>, the system may want a
* wider or shorter cursor than this value.
* @return The cursor.
*/
private static final Cursor getCustomCursor(Image image, Point hotspot,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -