Path: blob/master/src/java.desktop/share/classes/sun/swing/PrintingStatus.java
41153 views
/*1* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package sun.swing;2526import javax.swing.*;27import java.awt.*;28import java.awt.event.ActionEvent;29import java.awt.event.WindowAdapter;30import java.awt.event.WindowEvent;31import java.awt.print.PageFormat;32import java.awt.print.Printable;33import java.awt.print.PrinterException;34import java.awt.print.PrinterJob;35import java.text.MessageFormat;36import java.util.concurrent.atomic.AtomicBoolean;37import java.lang.reflect.InvocationTargetException;3839/**40* The {@code PrintingStatus} provides a dialog that displays progress41* of the printing job and provides a way to abort it42* <p>43* Methods of these class are thread safe, although most Swing methods44* are not. Please see45* <A HREF="https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html">Concurrency46* in Swing</A> for more information.47*48* @author Alexander Potochkin49* @since 1.650*/5152public class PrintingStatus {5354private final PrinterJob job;55private final Component parent;56private JDialog abortDialog;5758private JButton abortButton;59private JLabel statusLabel;60private MessageFormat statusFormat;61private final AtomicBoolean isAborted = new AtomicBoolean(false);6263// the action that will abort printing64@SuppressWarnings("serial") // anonymous class65private final Action abortAction = new AbstractAction() {66public void actionPerformed(ActionEvent ae) {67if (!isAborted.get()) {68isAborted.set(true);6970// update the status abortDialog to indicate aborting71abortButton.setEnabled(false);72abortDialog.setTitle(73UIManager.getString("PrintingDialog.titleAbortingText"));74statusLabel.setText(75UIManager.getString("PrintingDialog.contentAbortingText"));7677// cancel the PrinterJob78job.cancel();79}80}81};8283private final WindowAdapter closeListener = new WindowAdapter() {84public void windowClosing(WindowEvent we) {85abortAction.actionPerformed(null);86}87};8889/**90* Creates PrintingStatus instance91*92* @param parent a <code>Component</code> object to be used93* as parent component for PrintingStatus dialog94* @param job a <code>PrinterJob</code> object to be cancelled95* using this <code>PrintingStatus</code> dialog96* @return a <code>PrintingStatus</code> object97*/98public static PrintingStatus99createPrintingStatus(Component parent, PrinterJob job) {100return new PrintingStatus(parent, job);101}102103protected PrintingStatus(Component parent, PrinterJob job) {104this.job = job;105this.parent = parent;106}107108private void init() {109// prepare the status JOptionPane110String progressTitle =111UIManager.getString("PrintingDialog.titleProgressText");112113String dialogInitialContent =114UIManager.getString("PrintingDialog.contentInitialText");115116// this one's a MessageFormat since it must include the page117// number in its text118statusFormat = new MessageFormat(119UIManager.getString("PrintingDialog.contentProgressText"));120121String abortText =122UIManager.getString("PrintingDialog.abortButtonText");123String abortTooltip =124UIManager.getString("PrintingDialog.abortButtonToolTipText");125int abortMnemonic =126getInt("PrintingDialog.abortButtonMnemonic", -1);127int abortMnemonicIndex =128getInt("PrintingDialog.abortButtonDisplayedMnemonicIndex", -1);129130abortButton = new JButton(abortText);131abortButton.addActionListener(abortAction);132133abortButton.setToolTipText(abortTooltip);134if (abortMnemonic != -1) {135abortButton.setMnemonic(abortMnemonic);136}137if (abortMnemonicIndex != -1) {138abortButton.setDisplayedMnemonicIndex(abortMnemonicIndex);139}140statusLabel = new JLabel(dialogInitialContent);141JOptionPane abortPane = new JOptionPane(statusLabel,142JOptionPane.INFORMATION_MESSAGE,143JOptionPane.DEFAULT_OPTION,144null, new Object[]{abortButton},145abortButton);146abortPane.getActionMap().put("close", abortAction);147148// The dialog should be centered over the viewport if the table is in one149if (parent != null && parent.getParent() instanceof JViewport) {150abortDialog =151abortPane.createDialog(parent.getParent(), progressTitle);152} else {153abortDialog = abortPane.createDialog(parent, progressTitle);154}155// clicking the X button should not hide the dialog156abortDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);157abortDialog.addWindowListener(closeListener);158}159160/**161* Shows PrintingStatus dialog.162* if dialog is modal this method returns only163* after <code>dispose()</code> was called otherwise returns immediately164*165* @param isModal <code>true</code> this dialog should be modal;166* <code>false</code> otherwise.167* @see #dispose168*/169public void showModal(final boolean isModal) {170if (SwingUtilities.isEventDispatchThread()) {171showModalOnEDT(isModal);172} else {173try {174SwingUtilities.invokeAndWait(new Runnable() {175public void run() {176showModalOnEDT(isModal);177}178});179} catch(InterruptedException e) {180throw new RuntimeException(e);181} catch(InvocationTargetException e) {182Throwable cause = e.getCause();183if (cause instanceof RuntimeException) {184throw (RuntimeException) cause;185} else if (cause instanceof Error) {186throw (Error) cause;187} else {188throw new RuntimeException(cause);189}190}191}192}193194/**195* The EDT part of the showModal method.196*197* This method is to be called on the EDT only.198*/199private void showModalOnEDT(boolean isModal) {200assert SwingUtilities.isEventDispatchThread();201init();202abortDialog.setModal(isModal);203abortDialog.setVisible(true);204}205206/**207* Disposes modal PrintingStatus dialog208*209* @see #showModal(boolean)210*/211public void dispose() {212if (SwingUtilities.isEventDispatchThread()) {213disposeOnEDT();214} else {215SwingUtilities.invokeLater(new Runnable() {216public void run() {217disposeOnEDT();218}219});220}221}222223/**224* The EDT part of the dispose method.225*226* This method is to be called on the EDT only.227*/228private void disposeOnEDT() {229assert SwingUtilities.isEventDispatchThread();230if (abortDialog != null) {231abortDialog.removeWindowListener(closeListener);232abortDialog.dispose();233abortDialog = null;234}235}236237/**238* Returns whether the printng was aborted using this PrintingStatus239*240* @return whether the printng was aborted using this PrintingStatus241*/242public boolean isAborted() {243return isAborted.get();244}245246/**247* Returns printable which is used to track the current page being248* printed in this PrintingStatus249*250* @param printable to be used to create notification printable251* @return printable which is used to track the current page being252* printed in this PrintingStatus253* @throws NullPointerException if <code>printable</code> is <code>null</code>254*/255public Printable createNotificationPrintable(Printable printable) {256return new NotificationPrintable(printable);257}258259private class NotificationPrintable implements Printable {260private final Printable printDelegatee;261262public NotificationPrintable(Printable delegatee) {263if (delegatee == null) {264throw new NullPointerException("Printable is null");265}266this.printDelegatee = delegatee;267}268269public int print(final Graphics graphics,270final PageFormat pageFormat, final int pageIndex)271throws PrinterException {272273final int retVal =274printDelegatee.print(graphics, pageFormat, pageIndex);275if (retVal != NO_SUCH_PAGE && !isAborted()) {276if (SwingUtilities.isEventDispatchThread()) {277updateStatusOnEDT(pageIndex);278} else {279SwingUtilities.invokeLater(new Runnable() {280public void run() {281updateStatusOnEDT(pageIndex);282}283});284}285}286return retVal;287}288289/**290* The EDT part of the print method.291*292* This method is to be called on the EDT only.293*/294private void updateStatusOnEDT(int pageIndex) {295assert SwingUtilities.isEventDispatchThread();296Object[] pageNumber = new Object[]{297pageIndex + 1};298statusLabel.setText(statusFormat.format(pageNumber));299}300}301302/**303* Duplicated from UIManager to make it visible304*/305static int getInt(Object key, int defaultValue) {306Object value = UIManager.get(key);307if (value instanceof Integer) {308return ((Integer) value).intValue();309}310if (value instanceof String) {311try {312return Integer.parseInt((String) value);313} catch(NumberFormatException nfe) {314}315}316return defaultValue;317}318}319320321