| /* |
| * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code 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 |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package sun.swing; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.WindowAdapter; |
| import java.awt.event.WindowEvent; |
| import java.awt.print.PageFormat; |
| import java.awt.print.Printable; |
| import java.awt.print.PrinterException; |
| import java.awt.print.PrinterJob; |
| import java.text.MessageFormat; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| import java.lang.reflect.InvocationTargetException; |
| |
| /** |
| * The {@code PrintingStatus} provides a dialog that displays progress |
| * of the printing job and provides a way to abort it |
| * <p> |
| * Methods of these class are thread safe, although most Swing methods |
| * are not. Please see |
| * <A HREF="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html">Concurrency |
| * in Swing</A> for more information. |
| * |
| * @author Alexander Potochkin |
| * @since 1.6 |
| */ |
| |
| public class PrintingStatus { |
| |
| private final PrinterJob job; |
| private final Component parent; |
| private JDialog abortDialog; |
| |
| private JButton abortButton; |
| private JLabel statusLabel; |
| private MessageFormat statusFormat; |
| private final AtomicBoolean isAborted = new AtomicBoolean(false); |
| |
| // the action that will abort printing |
| @SuppressWarnings("serial") // anonymous class |
| private final Action abortAction = new AbstractAction() { |
| public void actionPerformed(ActionEvent ae) { |
| if (!isAborted.get()) { |
| isAborted.set(true); |
| |
| // update the status abortDialog to indicate aborting |
| abortButton.setEnabled(false); |
| abortDialog.setTitle( |
| UIManager.getString("PrintingDialog.titleAbortingText")); |
| statusLabel.setText( |
| UIManager.getString("PrintingDialog.contentAbortingText")); |
| |
| // cancel the PrinterJob |
| job.cancel(); |
| } |
| } |
| }; |
| |
| private final WindowAdapter closeListener = new WindowAdapter() { |
| public void windowClosing(WindowEvent we) { |
| abortAction.actionPerformed(null); |
| } |
| }; |
| |
| /** |
| * Creates PrintingStatus instance |
| * |
| * @param parent a <code>Component</code> object to be used |
| * as parent component for PrintingStatus dialog |
| * @param job a <code>PrinterJob</code> object to be cancelled |
| * using this <code>PrintingStatus</code> dialog |
| * @return a <code>PrintingStatus</code> object |
| */ |
| public static PrintingStatus |
| createPrintingStatus(Component parent, PrinterJob job) { |
| return new PrintingStatus(parent, job); |
| } |
| |
| protected PrintingStatus(Component parent, PrinterJob job) { |
| this.job = job; |
| this.parent = parent; |
| } |
| |
| private void init() { |
| // prepare the status JOptionPane |
| String progressTitle = |
| UIManager.getString("PrintingDialog.titleProgressText"); |
| |
| String dialogInitialContent = |
| UIManager.getString("PrintingDialog.contentInitialText"); |
| |
| // this one's a MessageFormat since it must include the page |
| // number in its text |
| statusFormat = new MessageFormat( |
| UIManager.getString("PrintingDialog.contentProgressText")); |
| |
| String abortText = |
| UIManager.getString("PrintingDialog.abortButtonText"); |
| String abortTooltip = |
| UIManager.getString("PrintingDialog.abortButtonToolTipText"); |
| int abortMnemonic = |
| getInt("PrintingDialog.abortButtonMnemonic", -1); |
| int abortMnemonicIndex = |
| getInt("PrintingDialog.abortButtonDisplayedMnemonicIndex", -1); |
| |
| abortButton = new JButton(abortText); |
| abortButton.addActionListener(abortAction); |
| |
| abortButton.setToolTipText(abortTooltip); |
| if (abortMnemonic != -1) { |
| abortButton.setMnemonic(abortMnemonic); |
| } |
| if (abortMnemonicIndex != -1) { |
| abortButton.setDisplayedMnemonicIndex(abortMnemonicIndex); |
| } |
| statusLabel = new JLabel(dialogInitialContent); |
| JOptionPane abortPane = new JOptionPane(statusLabel, |
| JOptionPane.INFORMATION_MESSAGE, |
| JOptionPane.DEFAULT_OPTION, |
| null, new Object[]{abortButton}, |
| abortButton); |
| abortPane.getActionMap().put("close", abortAction); |
| |
| // The dialog should be centered over the viewport if the table is in one |
| if (parent != null && parent.getParent() instanceof JViewport) { |
| abortDialog = |
| abortPane.createDialog(parent.getParent(), progressTitle); |
| } else { |
| abortDialog = abortPane.createDialog(parent, progressTitle); |
| } |
| // clicking the X button should not hide the dialog |
| abortDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); |
| abortDialog.addWindowListener(closeListener); |
| } |
| |
| /** |
| * Shows PrintingStatus dialog. |
| * if dialog is modal this method returns only |
| * after <code>dispose()</code> was called otherwise returns immediately |
| * |
| * @param isModal <code>true</code> this dialog should be modal; |
| * <code>false</code> otherwise. |
| * @see #dispose |
| */ |
| public void showModal(final boolean isModal) { |
| if (SwingUtilities.isEventDispatchThread()) { |
| showModalOnEDT(isModal); |
| } else { |
| try { |
| SwingUtilities.invokeAndWait(new Runnable() { |
| public void run() { |
| showModalOnEDT(isModal); |
| } |
| }); |
| } catch(InterruptedException e) { |
| throw new RuntimeException(e); |
| } catch(InvocationTargetException e) { |
| Throwable cause = e.getCause(); |
| if (cause instanceof RuntimeException) { |
| throw (RuntimeException) cause; |
| } else if (cause instanceof Error) { |
| throw (Error) cause; |
| } else { |
| throw new RuntimeException(cause); |
| } |
| } |
| } |
| } |
| |
| /** |
| * The EDT part of the showModal method. |
| * |
| * This method is to be called on the EDT only. |
| */ |
| private void showModalOnEDT(boolean isModal) { |
| assert SwingUtilities.isEventDispatchThread(); |
| init(); |
| abortDialog.setModal(isModal); |
| abortDialog.setVisible(true); |
| } |
| |
| /** |
| * Disposes modal PrintingStatus dialog |
| * |
| * @see #showModal(boolean) |
| */ |
| public void dispose() { |
| if (SwingUtilities.isEventDispatchThread()) { |
| disposeOnEDT(); |
| } else { |
| SwingUtilities.invokeLater(new Runnable() { |
| public void run() { |
| disposeOnEDT(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * The EDT part of the dispose method. |
| * |
| * This method is to be called on the EDT only. |
| */ |
| private void disposeOnEDT() { |
| assert SwingUtilities.isEventDispatchThread(); |
| if (abortDialog != null) { |
| abortDialog.removeWindowListener(closeListener); |
| abortDialog.dispose(); |
| abortDialog = null; |
| } |
| } |
| |
| /** |
| * Returns whether the printng was aborted using this PrintingStatus |
| * |
| * @return whether the printng was aborted using this PrintingStatus |
| */ |
| public boolean isAborted() { |
| return isAborted.get(); |
| } |
| |
| /** |
| * Returns printable which is used to track the current page being |
| * printed in this PrintingStatus |
| * |
| * @param printable to be used to create notification printable |
| * @return printable which is used to track the current page being |
| * printed in this PrintingStatus |
| * @throws NullPointerException if <code>printable</code> is <code>null</code> |
| */ |
| public Printable createNotificationPrintable(Printable printable) { |
| return new NotificationPrintable(printable); |
| } |
| |
| private class NotificationPrintable implements Printable { |
| private final Printable printDelegatee; |
| |
| public NotificationPrintable(Printable delegatee) { |
| if (delegatee == null) { |
| throw new NullPointerException("Printable is null"); |
| } |
| this.printDelegatee = delegatee; |
| } |
| |
| public int print(final Graphics graphics, |
| final PageFormat pageFormat, final int pageIndex) |
| throws PrinterException { |
| |
| final int retVal = |
| printDelegatee.print(graphics, pageFormat, pageIndex); |
| if (retVal != NO_SUCH_PAGE && !isAborted()) { |
| if (SwingUtilities.isEventDispatchThread()) { |
| updateStatusOnEDT(pageIndex); |
| } else { |
| SwingUtilities.invokeLater(new Runnable() { |
| public void run() { |
| updateStatusOnEDT(pageIndex); |
| } |
| }); |
| } |
| } |
| return retVal; |
| } |
| |
| /** |
| * The EDT part of the print method. |
| * |
| * This method is to be called on the EDT only. |
| */ |
| private void updateStatusOnEDT(int pageIndex) { |
| assert SwingUtilities.isEventDispatchThread(); |
| Object[] pageNumber = new Object[]{ |
| pageIndex + 1}; |
| statusLabel.setText(statusFormat.format(pageNumber)); |
| } |
| } |
| |
| /** |
| * Duplicated from UIManager to make it visible |
| */ |
| static int getInt(Object key, int defaultValue) { |
| Object value = UIManager.get(key); |
| if (value instanceof Integer) { |
| return ((Integer) value).intValue(); |
| } |
| if (value instanceof String) { |
| try { |
| return Integer.parseInt((String) value); |
| } catch(NumberFormatException nfe) { |
| } |
| } |
| return defaultValue; |
| } |
| } |