/*
* Copyright 2001-2014 Aspose Pty Ltd. All Rights Reserved.
*
* This file is part of Aspose.Words. The source code in this file
* is only intended as a supplement to the documentation, and is provided
* "as is", without warranty of any kind, either expressed or implied.
*/
package com.aspose.words.examples.rendering_printing;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.PageRanges;
import javax.swing.*;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Pageable;
import java.awt.print.Printable;
import java.awt.print.PrinterJob;
public class PrintPreviewDialog extends JFrame {
/**
* The dialog components.
*/
private JButton printButton;
private JComboBox zoomComboBox;
private JProgressBar progressBar;
private JButton closeButton;
private JPanel contentPane;
private JTextPane pageNumberTextBox;
private BasicArrowButton previousPageButton;
private BasicArrowButton firstPageButton;
private BasicArrowButton lastPageButton;
private BasicArrowButton nextPageButton;
private JLabel imageLabel;
private JScrollPane documentViewer;
private JButton pageSetupButton;
/**
* Private instance members.
*/
private Printable mPrintableDoc;
private Pageable mPageableDoc;
private boolean mIsOpened = true;
private int mPreviousZoomIndex;
private int mStartPage = 1;
private int mTotalPages = -1;
private int mCurrentPage = 1;
private int mDocumentPages = -1;
private boolean mPrintSelected = false;
private PrinterJob mPrintJob;
private PageFormat mPageFormat;
private PrintRequestAttributeSet mAttributeSet;
/**
* Creates a new instance of PrintPreviewDialog for the given printable object. Since this object
* does not define formatting for each page the preview dialog presents a page setup option
* where the user can specify custom page settings for the document.
*
* @param printJob The print job for the given document.
* @param doc The printable document.
*/
public PrintPreviewDialog(PrinterJob printJob, Printable doc) {
mPrintableDoc = doc;
mPrintJob = printJob;
// In Java 1.6 and above we would use the getPageFormat(PrintRequestAttributeSet) property of a
// class implementing printable to retrieve the currently specified page format. However this
// property is not available in versions below versions so we need to assume the default page instead.
$$$setupUI$$$();
mPageFormat = mPrintJob.defaultPage();
init();
}
/**
* Creates a new instance of PrintPreviewDialog for the given pageable object. Since this object
* defines formatting for each page the page setup option on the preview dialog is disabled.
*
* @param doc The pageable document.
*/
public PrintPreviewDialog(Pageable doc) {
mPageableDoc = doc;
$$$setupUI$$$();
mTotalPages = doc.getNumberOfPages();
mDocumentPages = mTotalPages;
init();
}
public void setPrinterAttributes(PrintRequestAttributeSet attributes) {
// Store the printer attributes for use with the page dialog.
mAttributeSet = attributes;
// Extract the page range from the printer attributes if that property is present.
findPageRangeFromAttributes(attributes);
}
public void init() {
// Setup the main window
setContentPane(contentPane);
pack();
setTitle("Print preview");
// Center the dialog in the center of the page.
setLocationRelativeTo(null);
// Add zoom options.
populateZoomComboBox();
// Pageable print classes already have page formatting applied so disable page setup button.
if (mPageableDoc != null)
pageSetupButton.setEnabled(false);
// Make the page number centered horizontally.
SimpleAttributeSet aSet = new SimpleAttributeSet();
StyleConstants.setFontFamily(aSet, "Arial");
StyleConstants.setAlignment(aSet, StyleConstants.ALIGN_CENTER);
pageNumberTextBox.setParagraphAttributes(aSet, true);
// Setup the appropriate handlers.
printButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onPrint();
}
});
pageSetupButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onPageSetup();
}
});
zoomComboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onZoomChanged();
}
});
firstPageButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onFirstPageSelected();
}
});
previousPageButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onPreviousPageSelected();
}
});
lastPageButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onLastPageSelected();
}
});
nextPageButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onNextPageSelected();
}
});
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
closeWindow();
}
});
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
closeWindow();
}
});
contentPane.registerKeyboardAction(new ActionListener() {
public void actionPerformed(ActionEvent e) {
closeWindow();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
}
/**
* Called to display the print preview dialog.
*/
public boolean display() {
// Activate the window.
setVisible(true);
// Render the current page.
setPageToDisplay(mCurrentPage);
// This causes the JFrame to act like modal. We want to use a JFrame in this way and not JDialog so
// we can have a taskbar icon for this window.
while (mIsOpened) {
}
// Return whether the user pressed print or close.
return mPrintSelected;
}
/**
* Renders the current page index of the document to image based on the current zoom factor and displays it on a JScrollPane.
*/
private int renderImageAndDisplay() {
// Set the progress bar to loading.
progressBar.setVisible(true);
progressBar.setIndeterminate(true);
BufferedImage img = null;
Graphics2D g;
// The zoom factor currently selected.
double zoomModifier = getCurrentZoomModifier();
// Clear the current image.
imageLabel.setIcon(null);
int result;
// Find the format of the current page from either the current pageable or printable object we are printing with.
PageFormat format = mPageableDoc != null ? mPageableDoc.getPageFormat(mCurrentPage - 1) : mPageFormat;
try {
img = new BufferedImage((int) (format.getWidth() * zoomModifier), (int) (format.getHeight() * zoomModifier), BufferedImage.TYPE_INT_RGB);
g = img.createGraphics();
// Fill the background white and add a black border.
g.setColor(Color.WHITE);
g.fillRect(0, 0, img.getWidth(), img.getHeight());
g.setColor(Color.BLACK);
g.drawRect(0, 0, img.getWidth() - 1, img.getHeight() - 1);
// Scale based on zoom factor.
g.scale(zoomModifier, zoomModifier);
// We must re-size the image label so scrolling works properly.
imageLabel.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
imageLabel.setMinimumSize(new Dimension(img.getWidth(), img.getHeight()));
imageLabel.setMaximumSize(new Dimension(img.getWidth(), img.getHeight()));
// Call the pageable or printable class to render the specified page onto our image object.
if (mPageableDoc != null)
result = mPageableDoc.getPrintable(mCurrentPage - 1).print(g, format, mCurrentPage - 1);
else
result = mPrintableDoc.print(g, format, mCurrentPage - 1);
} catch (Exception e) {
// We'll end up here if there is a problem with rendering or we have gone past the valid page range.
// Display a blank page and return the result so we know we have gone past the last page.
return Printable.NO_SUCH_PAGE;
} finally {
// Hide the progress bar.
progressBar.setVisible(false);
}
// Display the rendered page.
imageLabel.setIcon(new ImageIcon(img));
return result;
}
/**
* Finds the page range selected by the user by the printer attributes.
*/
private void findPageRangeFromAttributes(PrintRequestAttributeSet attributes) {
if (attributes.containsKey(PageRanges.class)) {
int[][] pageRanges = ((PageRanges) attributes.get(PageRanges.class)).getMembers();
int startPage = pageRanges[0][0];
// If we know the number of pages in the document and the user specified value is out of range then use
// the first page instead. Otherwise the user specified value is used which is checked later on if it's
// valid or not.
if (knowsDocumentPages()) {
if (startPage > mDocumentPages)
mStartPage = 1;
else
mStartPage = startPage;
} else {
mStartPage = startPage;
}
mCurrentPage = mStartPage;
// If we know how many pages the document has then we need to make sure the user user specified end page
// does not go beyond this limit. Otherwise use this value which will be handled later on if it's found
// to be invalid.
if (knowsDocumentPages())
mTotalPages = Math.min(mDocumentPages, pageRanges[0][1]);
else
mTotalPages = pageRanges[0][1];
}
}
/**
* Changes the current page to display.
*/
private void setPageToDisplay(int page) {
mCurrentPage = page;
updateCurrentPage();
}
/**
* Adds the zoom options to the combobox.
*/
private void populateZoomComboBox() {
zoomComboBox.addItem("10%");
zoomComboBox.addItem("25%");
zoomComboBox.addItem("50%");
zoomComboBox.addItem("75%");
zoomComboBox.addItem("100%");
zoomComboBox.addItem("150%");
zoomComboBox.addItem("200%");
zoomComboBox.setSelectedIndex(4);
mPreviousZoomIndex = zoomComboBox.getSelectedIndex();
}
/**
* Returns the zoom modifier for the given zoom level.
*/
private double getCurrentZoomModifier() {
String zoomLevel = ((String) zoomComboBox.getSelectedItem()).replace("%", "");
// Percent increase of the original image to make the page displayed at 100%.
double hundredPercent = 1.5;
// Zoom level percent as a decimal.
double zoomValue = Double.parseDouble(zoomLevel) / 100;
return hundredPercent * zoomValue;
}
/**
* Verifies the page index based off the known valid page range and if valid calls for the new page to be rendered.
* Depending if a page range was specified by the user we may or may not know the final page number yet. If we don't then
* it is found later when each page is rendered.
*/
private void updateCurrentPage() {
// If we don't know the total pages in the document then we also won't know the final page count in the document
// until we try to render outside the valid index. Until then allow the user to move forward no matter the current
// page index.
if (knowsDocumentPages()) {
if (mCurrentPage > mTotalPages)
return;
}
// Can't move past the first page.
if (mCurrentPage < mStartPage)
return;
int result = renderImageAndDisplay();
// If the rendering of the previous page resulted in "NO_SUCH_PAGE" then
// we must have found the last page in the document. The appropriate page numbers
// needs to be updated.
if (result == Printable.NO_SUCH_PAGE) {
// If this occurs at the very start of the document preview then the intial starting page
// must be out of bounds. Default to page one instead.
if (mCurrentPage == mStartPage) {
mCurrentPage = 1;
mStartPage = 1;
} else {
mCurrentPage--;
// If the next page document button was pressed and there's no futher pages to render then
// we must have found the end page of the document.
mTotalPages = mCurrentPage;
mDocumentPages = mCurrentPage;
}
// Render the previous page which is the last page in the document.
renderImageAndDisplay();
}
pageNumberTextBox.setText(String.valueOf((mCurrentPage - mStartPage) + 1));
updateArrowButtons();
}
/**
* Enables or disables arrow buttons based off the current state of the page index.
*/
private void updateArrowButtons() {
if (mCurrentPage > mStartPage) {
firstPageButton.setEnabled(true);
previousPageButton.setEnabled(true);
} else {
firstPageButton.setEnabled(false);
previousPageButton.setEnabled(false);
}
if (knowsDocumentPages()) {
if (mCurrentPage == mTotalPages) {
nextPageButton.setEnabled(false);
lastPageButton.setEnabled(false);
} else {
nextPageButton.setEnabled(true);
lastPageButton.setEnabled(true);
}
} else {
// If we don't know how many pages are in the specified document then we cannot skip to the last page.
lastPageButton.setEnabled(false);
if (mCurrentPage == mTotalPages)
nextPageButton.setEnabled(false);
else
nextPageButton.setEnabled(true);
}
}
/**
* Returns true if the last page number of the document is known.
*/
private boolean knowsDocumentPages() {
return mDocumentPages > 0;
}
/**
* Called when user presses the cross on the window or the escape key to close the program.
*/
private void closeWindow() {
setVisible(false);
mIsOpened = false;
dispose();
}
/**
* Called when the user press the Page Setup button. A screen is displayed which allows
* the user to change the page setting of the document before printing.
*/
private void onPageSetup() {
// Retrieve the new page format from either the attributes if specified otherwise the previous page formatting.
if (mAttributeSet != null)
mPageFormat = mPrintJob.pageDialog(mAttributeSet);
else
mPageFormat = mPrintJob.pageDialog(mPageFormat);
// Print using the new page format.
mPrintJob.setPrintable(mPrintableDoc, mPageFormat);
// Update the preview of the new settings.
updateCurrentPage();
}
/**
* Called when the user presses the print button. Returns true to specify that printing was accepted
* and closes the window.
*/
private void onPrint() {
mPrintSelected = true;
closeWindow();
}
/**
* Re-renders the document page if the zoom level has been changed.
*/
private void onZoomChanged() {
if (mPreviousZoomIndex != zoomComboBox.getSelectedIndex()) {
mPreviousZoomIndex = zoomComboBox.getSelectedIndex();
renderImageAndDisplay();
}
}
/**
* Called when the first page button is selected. Displays the first page.
*/
private void onFirstPageSelected() {
setPageToDisplay(mStartPage);
}
/**
* Called when the next page button is selected. Displays the next page.
*/
private void onNextPageSelected() {
setPageToDisplay(mCurrentPage + 1);
}
/**
* Called when the last page button is selected. Displays the last page.
*/
private void onLastPageSelected() {
setPageToDisplay(mTotalPages);
}
/**
* Called when the previous page button is selected. Displays the previous page.
*/
private void onPreviousPageSelected() {
setPageToDisplay(mCurrentPage - 1);
}
/**
* Creates the custom arrow buttons.
*/
private void createUIComponents() {
previousPageButton = new BasicArrowButton(BasicArrowButton.WEST);
nextPageButton = new BasicArrowButton(BasicArrowButton.EAST);
firstPageButton = new DoubleArrowButton(BasicArrowButton.WEST);
lastPageButton = new DoubleArrowButton(BasicArrowButton.EAST);
}
/**
* Method generated by IntelliJ IDEA GUI Designer
* >>> IMPORTANT!! <<<
* DO NOT edit this method OR call it in your code!
*
* @noinspection ALL
*/
private void $$$setupUI$$$() {
createUIComponents();
contentPane = new JPanel();
contentPane.setLayout(new BorderLayout(0, 0));
contentPane.setMaximumSize(new Dimension(1000, 700));
contentPane.setMinimumSize(new Dimension(1000, 700));
contentPane.setPreferredSize(new Dimension(1000, 700));
contentPane.setRequestFocusEnabled(true);
final JToolBar toolBar1 = new JToolBar();
contentPane.add(toolBar1, BorderLayout.NORTH);
printButton = new JButton();
printButton.setMargin(new Insets(2, 14, 2, 14));
printButton.setText("Print");
toolBar1.add(printButton);
final JToolBar.Separator toolBar$Separator1 = new JToolBar.Separator();
toolBar1.add(toolBar$Separator1);
pageSetupButton = new JButton();
pageSetupButton.setText("Page Setup");
toolBar1.add(pageSetupButton);
final JToolBar.Separator toolBar$Separator2 = new JToolBar.Separator();
toolBar1.add(toolBar$Separator2);
zoomComboBox = new JComboBox();
zoomComboBox.setBackground(new Color(-1));
zoomComboBox.setMaximumSize(new Dimension(130, 30));
zoomComboBox.setMinimumSize(new Dimension(130, 23));
zoomComboBox.setRequestFocusEnabled(false);
toolBar1.add(zoomComboBox);
final JToolBar.Separator toolBar$Separator3 = new JToolBar.Separator();
toolBar1.add(toolBar$Separator3);
final JPanel panel1 = new JPanel();
panel1.setLayout(new com.intellij.uiDesigner.core.GridLayoutManager(1, 5, new Insets(0, 0, 0, 0), -1, -1));
panel1.setMaximumSize(new Dimension(175, 2147483647));
panel1.setMinimumSize(new Dimension(175, 24));
panel1.setOpaque(false);
toolBar1.add(panel1);
panel1.add(firstPageButton, new com.intellij.uiDesigner.core.GridConstraints(0, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_NONE, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_FIXED, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
panel1.add(previousPageButton, new com.intellij.uiDesigner.core.GridConstraints(0, 1, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_NONE, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
panel1.add(nextPageButton, new com.intellij.uiDesigner.core.GridConstraints(0, 3, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_NONE, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
panel1.add(lastPageButton, new com.intellij.uiDesigner.core.GridConstraints(0, 4, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_NONE, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
pageNumberTextBox = new JTextPane();
pageNumberTextBox.setEditable(false);
panel1.add(pageNumberTextBox, new com.intellij.uiDesigner.core.GridConstraints(0, 2, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_BOTH, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, new Dimension(40, 20), new Dimension(40, 20), new Dimension(40, 20), 0, false));
final JToolBar.Separator toolBar$Separator4 = new JToolBar.Separator();
toolBar1.add(toolBar$Separator4);
closeButton = new JButton();
closeButton.setText("Close");
toolBar1.add(closeButton);
documentViewer = new JScrollPane();
documentViewer.setVerticalScrollBarPolicy(20);
contentPane.add(documentViewer, BorderLayout.CENTER);
imageLabel = new JLabel();
imageLabel.setHorizontalAlignment(0);
imageLabel.setHorizontalTextPosition(0);
imageLabel.setMaximumSize(new Dimension(500, 500));
imageLabel.setMinimumSize(new Dimension(500, 500));
imageLabel.setPreferredSize(new Dimension(500, 500));
imageLabel.setRequestFocusEnabled(true);
imageLabel.setText("");
documentViewer.setViewportView(imageLabel);
final JPanel panel2 = new JPanel();
panel2.setLayout(new com.intellij.uiDesigner.core.GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
contentPane.add(panel2, BorderLayout.SOUTH);
progressBar = new JProgressBar();
progressBar.setPreferredSize(new Dimension(60, 14));
panel2.add(progressBar, new com.intellij.uiDesigner.core.GridConstraints(0, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_NONE, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(300, 10), null, 0, false));
}
/**
* @noinspection ALL
*/
public JComponent $$$getRootComponent$$$() {
return contentPane;
}
/**
* A simple extension of the BasicArrowButton which displays two arrows instead of one.
*/
public class DoubleArrowButton extends BasicArrowButton {
public DoubleArrowButton(int type) {
super(type);
mArrowType = type;
}
public void paintTriangle(Graphics g, int x, int y, int size,
int direction, boolean isEnabled) {
super.paintTriangle(g, x - (size / 2), y, size, mArrowType, isEnabled);
super.paintTriangle(g, x + (size / 2), y, size, mArrowType, isEnabled);
}
private int mArrowType;
}
}