jdk/src/java.desktop/share/classes/sun/swing/text/TextComponentPrintable.java
author prr
Mon, 14 Nov 2016 09:59:36 -0800
changeset 42216 621af0ebf6c4
parent 30948 0a0972d3b58d
permissions -rw-r--r--
8169518: Suppress Deprecation warnings for deprecated Swing APIs Reviewed-by: alexsch, ssadetsky
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
22618
927e4fe6cb24 8033221: Fix serial lint warnings in sun.swing.*
darcy
parents: 10099
diff changeset
     2
 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
package sun.swing.text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.awt.ComponentOrientation;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.awt.Dimension;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.awt.Font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.awt.FontMetrics;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.awt.Graphics;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.awt.Graphics2D;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.awt.Insets;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.awt.Rectangle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.awt.Component;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.awt.Container;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.awt.font.FontRenderContext;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.awt.print.PageFormat;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.awt.print.Printable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.awt.print.PrinterException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.text.MessageFormat;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.util.ArrayList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import java.util.Collections;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import java.util.List;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import java.util.concurrent.Callable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import java.util.concurrent.ExecutionException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
import java.util.concurrent.FutureTask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
import java.util.concurrent.atomic.AtomicReference;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
10099
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
    50
import javax.swing.*;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
import javax.swing.border.Border;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
import javax.swing.border.TitledBorder;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
import javax.swing.text.BadLocationException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
import javax.swing.text.JTextComponent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
import javax.swing.text.Document;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
import javax.swing.text.EditorKit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
import javax.swing.text.AbstractDocument;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
import javax.swing.text.html.HTMLDocument;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
import javax.swing.text.html.HTML;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
import sun.font.FontDesignMetrics;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
import sun.swing.text.html.FrameEditorPaneTag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * An implementation of {@code Printable} to print {@code JTextComponent} with
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * the header and footer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * <h1>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * WARNING: this class is to be used in
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * javax.swing.text.JTextComponent only.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * </h1>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * The implementation creates a new {@code JTextComponent} ({@code printShell})
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * to print the content using the {@code Document}, {@code EditorKit} and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * rendering-affecting properties from the original {@code JTextComponent}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * {@code printShell} is laid out on the first {@code print} invocation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 * This class can be used on any thread. Part of the implementation is executed
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 * on the EDT though.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 * @author Igor Kushnirskiy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 * @since 1.6
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
public class TextComponentPrintable implements CountingPrintable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    private static final int LIST_SIZE = 1000;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    private boolean isLayouted = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     * The text component to print.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    private final JTextComponent textComponentToPrint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
     * The FontRenderContext to layout and print with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    private final AtomicReference<FontRenderContext> frc =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
        new AtomicReference<FontRenderContext>(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
     * Special text component used to print to the printer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    private final JTextComponent printShell;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    private final MessageFormat headerFormat;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
    private final MessageFormat footerFormat;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
    private static final float HEADER_FONT_SIZE = 18.0f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
    private static final float FOOTER_FONT_SIZE = 12.0f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    private final Font headerFont;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    private final Font footerFont;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * stores metrics for the unhandled rows. The only metrics we need are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     * yStart and yEnd when row is handled by updatePagesMetrics it is removed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     * from the list. Thus the head of the list is the fist row to handle.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     * sorted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    private final List<IntegerSegment> rowsMetrics;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
     * thread-safe list for storing pages metrics. The only metrics we need are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
     * yStart and yEnd.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
     * It has to be thread-safe since metrics are calculated on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
     * the printing thread and accessed on the EDT thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
     * sorted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    private final List<IntegerSegment> pagesMetrics;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
     * Returns {@code TextComponentPrintable} to print {@code textComponent}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
     * @param textComponent {@code JTextComponent} to print
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
     * @param headerFormat the page header, or {@code null} for none
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
     * @param footerFormat the page footer, or {@code null} for none
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
     * @return {@code TextComponentPrintable} to print {@code textComponent}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    public static Printable getPrintable(final JTextComponent textComponent,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            final MessageFormat headerFormat,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            final MessageFormat footerFormat) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        if (textComponent instanceof JEditorPane
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                && isFrameSetDocument(textComponent.getDocument())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            //for document with frames we create one printable per
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            //frame and merge them with the CompoundPrintable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            List<JEditorPane> frames = getFrames((JEditorPane) textComponent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
            List<CountingPrintable> printables =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
                new ArrayList<CountingPrintable>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
            for (JEditorPane frame : frames) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
                printables.add((CountingPrintable)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                               getPrintable(frame, headerFormat, footerFormat));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            return new CompoundPrintable(printables);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
            return new TextComponentPrintable(textComponent,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
               headerFormat, footerFormat);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
     * Checks whether the document has frames. Only HTMLDocument might
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
     * have frames.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
     * @param document the {@code Document} to check
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
     * @return {@code true} if the {@code document} has frames
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    private static boolean isFrameSetDocument(final Document document) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        boolean ret = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
        if (document instanceof HTMLDocument) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
            HTMLDocument htmlDocument = (HTMLDocument)document;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            if (htmlDocument.getIterator(HTML.Tag.FRAME).isValid()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                ret = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
     * Returns frames under the {@code editor}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
     * The frames are created if necessary.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
     * @param editor the {@JEditorPane} to find the frames for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
     * @return list of all frames
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    private static List<JEditorPane> getFrames(final JEditorPane editor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        List<JEditorPane> list = new ArrayList<JEditorPane>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        getFrames(editor, list);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        if (list.size() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            //the frames have not been created yet.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
            //let's trigger the frames creation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
            createFrames(editor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
            getFrames(editor, list);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        return list;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
     * Adds all {@code JEditorPanes} under {@code container} tagged by {@code
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
     * FrameEditorPaneTag} to the {@code list}. It adds only top
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
     * level {@code JEditorPanes}.  For instance if there is a frame
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
     * inside the frame it will return the top frame only.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
     *
30948
0a0972d3b58d 6587235: Incorrect javadoc: "no parameter" in 2d source code
serb
parents: 25859
diff changeset
   215
     * @param container the container to find all frames under
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
     * @param list {@code List} to append the results too
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
    private static void getFrames(final Container container, List<JEditorPane> list) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        for (Component c : container.getComponents()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
            if (c instanceof FrameEditorPaneTag
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
                && c instanceof JEditorPane ) { //it should be always JEditorPane
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                list.add((JEditorPane) c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                if (c instanceof Container) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                    getFrames((Container) c, list);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     * Triggers the frames creation for {@code JEditorPane}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
     * @param editor the {@code JEditorPane} to create frames for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
    private static void createFrames(final JEditorPane editor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        Runnable doCreateFrames =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            new Runnable() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                public void run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                    final int WIDTH = 500;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                    final int HEIGHT = 500;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                    CellRendererPane rendererPane = new CellRendererPane();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
                    rendererPane.add(editor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
                    //the values do not matter
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                    //we only need to get frames created
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
                    rendererPane.setSize(WIDTH, HEIGHT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
            };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
        if (SwingUtilities.isEventDispatchThread()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            doCreateFrames.run();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                SwingUtilities.invokeAndWait(doCreateFrames);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
            } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
                if (e instanceof RuntimeException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
                    throw (RuntimeException) e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
                    throw new RuntimeException(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
     * Constructs  {@code TextComponentPrintable} to print {@code JTextComponent}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
     * {@code textComponent} with {@code headerFormat} and {@code footerFormat}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
     * @param textComponent {@code JTextComponent} to print
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
     * @param headerFormat the page header or {@code null} for none
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
     * @param footerFormat the page footer or {@code null} for none
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
    private TextComponentPrintable(JTextComponent textComponent,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
            MessageFormat headerFormat,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            MessageFormat footerFormat) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        this.textComponentToPrint = textComponent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        this.headerFormat = headerFormat;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
        this.footerFormat = footerFormat;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
        headerFont = textComponent.getFont().deriveFont(Font.BOLD,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            HEADER_FONT_SIZE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        footerFont = textComponent.getFont().deriveFont(Font.PLAIN,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            FOOTER_FONT_SIZE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        this.pagesMetrics =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
            Collections.synchronizedList(new ArrayList<IntegerSegment>());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        this.rowsMetrics = new ArrayList<IntegerSegment>(LIST_SIZE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        this.printShell = createPrintShell(textComponent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     * creates a printShell.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     * It creates closest text component to {@code textComponent}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
     * which uses {@code frc} from the {@code TextComponentPrintable}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
     * for the {@code getFontMetrics} method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
     * @param textComponent {@code JTextComponent} to create a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     *        printShell for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     * @return the print shell
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
    private JTextComponent createPrintShell(final JTextComponent textComponent) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
        if (SwingUtilities.isEventDispatchThread()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            return createPrintShellOnEDT(textComponent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            FutureTask<JTextComponent> futureCreateShell =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
                new FutureTask<JTextComponent>(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
                    new Callable<JTextComponent>() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
                        public JTextComponent call() throws Exception {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                            return createPrintShellOnEDT(textComponent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                    });
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
            SwingUtilities.invokeLater(futureCreateShell);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
                return futureCreateShell.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
            } catch (InterruptedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
                throw new RuntimeException(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
            } catch (ExecutionException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
                Throwable cause = e.getCause();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
                if (cause instanceof Error) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
                    throw (Error) cause;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
                if (cause instanceof RuntimeException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
                    throw (RuntimeException) cause;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
                throw new AssertionError(cause);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
    }
22618
927e4fe6cb24 8033221: Fix serial lint warnings in sun.swing.*
darcy
parents: 10099
diff changeset
   327
    @SuppressWarnings("serial") // anonymous class inside
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
    private JTextComponent createPrintShellOnEDT(final JTextComponent textComponent) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        assert SwingUtilities.isEventDispatchThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        JTextComponent ret = null;
10099
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   332
        if (textComponent instanceof JPasswordField) {
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   333
            ret =
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   334
                new JPasswordField() {
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   335
                    {
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   336
                        setEchoChar(((JPasswordField) textComponent).getEchoChar());
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   337
                        setHorizontalAlignment(
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   338
                            ((JTextField) textComponent).getHorizontalAlignment());
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   339
                    }
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   340
                    @Override
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   341
                    public FontMetrics getFontMetrics(Font font) {
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   342
                        return (frc.get() == null)
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   343
                            ? super.getFontMetrics(font)
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   344
                            : FontDesignMetrics.getMetrics(font, frc.get());
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   345
                    }
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   346
                };
1887eb63f84c 6509273: Password in JPasswordField gets Printed in clear text
rupashka
parents: 5506
diff changeset
   347
        } else if (textComponent instanceof JTextField) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
            ret =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                new JTextField() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
                    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
                        setHorizontalAlignment(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
                            ((JTextField) textComponent).getHorizontalAlignment());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
                    @Override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                    public FontMetrics getFontMetrics(Font font) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
                        return (frc.get() == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
                            ? super.getFontMetrics(font)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
                            : FontDesignMetrics.getMetrics(font, frc.get());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
                };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        } else if (textComponent instanceof JTextArea) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
            ret =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
                new JTextArea() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
                    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                        JTextArea textArea = (JTextArea) textComponent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                        setLineWrap(textArea.getLineWrap());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
                        setWrapStyleWord(textArea.getWrapStyleWord());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
                        setTabSize(textArea.getTabSize());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
                    @Override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
                    public FontMetrics getFontMetrics(Font font) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
                        return (frc.get() == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
                            ? super.getFontMetrics(font)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
                            : FontDesignMetrics.getMetrics(font, frc.get());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
                };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        } else if (textComponent instanceof JTextPane) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            ret =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                new JTextPane() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
                    @Override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
                    public FontMetrics getFontMetrics(Font font) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
                        return (frc.get() == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
                            ? super.getFontMetrics(font)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
                            : FontDesignMetrics.getMetrics(font, frc.get());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                    @Override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
                    public EditorKit getEditorKit() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
                        if (getDocument() == textComponent.getDocument()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                            return ((JTextPane) textComponent).getEditorKit();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                            return super.getEditorKit();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
                };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        } else if (textComponent instanceof JEditorPane) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
            ret =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
                new JEditorPane() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
                    @Override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
                    public FontMetrics getFontMetrics(Font font) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
                        return (frc.get() == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                            ? super.getFontMetrics(font)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
                            : FontDesignMetrics.getMetrics(font, frc.get());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
                    @Override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
                    public EditorKit getEditorKit() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
                        if (getDocument() == textComponent.getDocument()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
                            return ((JEditorPane) textComponent).getEditorKit();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
                            return super.getEditorKit();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
                };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
        //want to occupy the whole width and height by text
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
        ret.setBorder(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        //set properties from the component to print
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        ret.setOpaque(textComponent.isOpaque());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
        ret.setEditable(textComponent.isEditable());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        ret.setEnabled(textComponent.isEnabled());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        ret.setFont(textComponent.getFont());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        ret.setBackground(textComponent.getBackground());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
        ret.setForeground(textComponent.getForeground());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        ret.setComponentOrientation(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
            textComponent.getComponentOrientation());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
        if (ret instanceof JEditorPane) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
            ret.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                textComponent.getClientProperty(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                JEditorPane.HONOR_DISPLAY_PROPERTIES));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
            ret.putClientProperty(JEditorPane.W3C_LENGTH_UNITS,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
                textComponent.getClientProperty(JEditorPane.W3C_LENGTH_UNITS));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
            ret.putClientProperty("charset",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
                textComponent.getClientProperty("charset"));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        ret.setDocument(textComponent.getDocument());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
     * Returns the number of pages in this printable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
     * This number is defined only after {@code print} returns NO_SUCH_PAGE.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
     * @return the number of pages.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
    public int getNumberOfPages() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
        return pagesMetrics.size();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
     * See Printable.print for the API description.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
     * There are two parts in the implementation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
     * First part (print) is to be called on the printing thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
     * Second part (printOnEDT) is to be called on the EDT only.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
     * print triggers printOnEDT
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
    public int print(final Graphics graphics,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            final PageFormat pf,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
            final int pageIndex) throws PrinterException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
        if (!isLayouted) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
            if (graphics instanceof Graphics2D) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
                frc.set(((Graphics2D)graphics).getFontRenderContext());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
            layout((int)Math.floor(pf.getImageableWidth()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
            calculateRowsMetrics();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
        if (!SwingUtilities.isEventDispatchThread()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
            Callable<Integer> doPrintOnEDT = new Callable<Integer>() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
                public Integer call() throws Exception {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                    return printOnEDT(graphics, pf, pageIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
            };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
            FutureTask<Integer> futurePrintOnEDT =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
                new FutureTask<Integer>(doPrintOnEDT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
            SwingUtilities.invokeLater(futurePrintOnEDT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                ret = futurePrintOnEDT.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
            } catch (InterruptedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                throw new RuntimeException(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
            } catch (ExecutionException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
                Throwable cause = e.getCause();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
                if (cause instanceof PrinterException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
                    throw (PrinterException)cause;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                } else if (cause instanceof RuntimeException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                    throw (RuntimeException) cause;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
                } else if (cause instanceof Error) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
                    throw (Error) cause;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                    throw new RuntimeException(cause);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
            ret = printOnEDT(graphics, pf, pageIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
     * The EDT part of the print method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
     * This method is to be called on the EDT only. Layout should be done before
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
     * calling this method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
    private int printOnEDT(final Graphics graphics,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
            final PageFormat pf,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            final int pageIndex) throws PrinterException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
        assert SwingUtilities.isEventDispatchThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        Border border = BorderFactory.createEmptyBorder();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
        //handle header and footer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        if (headerFormat != null || footerFormat != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
            //Printable page enumeration is 0 base. We need 1 based.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
            Object[] formatArg = new Object[]{Integer.valueOf(pageIndex + 1)};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
            if (headerFormat != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
                border = new TitledBorder(border,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
                    headerFormat.format(formatArg),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
                    TitledBorder.CENTER, TitledBorder.ABOVE_TOP,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
                    headerFont, printShell.getForeground());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
            if (footerFormat != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
                border = new TitledBorder(border,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
                    footerFormat.format(formatArg),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
                    TitledBorder.CENTER, TitledBorder.BELOW_BOTTOM,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
                    footerFont, printShell.getForeground());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
        Insets borderInsets = border.getBorderInsets(printShell);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
        updatePagesMetrics(pageIndex,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
            (int)Math.floor(pf.getImageableHeight()) - borderInsets.top
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
                           - borderInsets.bottom);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
        if (pagesMetrics.size() <= pageIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
            return NO_SUCH_PAGE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
        Graphics2D g2d = (Graphics2D)graphics.create();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
        g2d.translate(pf.getImageableX(), pf.getImageableY());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        border.paintBorder(printShell, g2d, 0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            (int)Math.floor(pf.getImageableWidth()),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
            (int)Math.floor(pf.getImageableHeight()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
        g2d.translate(0, borderInsets.top);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        //want to clip only vertically
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
        Rectangle clip = new Rectangle(0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
            (int) pf.getWidth(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
            pagesMetrics.get(pageIndex).end
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
                - pagesMetrics.get(pageIndex).start + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
        g2d.clip(clip);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        int xStart = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
        if (ComponentOrientation.RIGHT_TO_LEFT ==
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
                printShell.getComponentOrientation()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
            xStart = (int) pf.getImageableWidth() - printShell.getWidth();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        g2d.translate(xStart, - pagesMetrics.get(pageIndex).start);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        printShell.print(g2d);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        g2d.dispose();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
        return Printable.PAGE_EXISTS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
    private boolean needReadLock = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
     * Tries to release document's readlock
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
     * Note: Not to be called on the EDT.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
    private void releaseReadLock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        assert ! SwingUtilities.isEventDispatchThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
        Document document = textComponentToPrint.getDocument();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        if (document instanceof AbstractDocument) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
                ((AbstractDocument) document).readUnlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
                needReadLock = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            } catch (Error ignore) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
                // readUnlock() might throw StateInvariantError
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
     * Tries to acquire document's readLock if it was released
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
     * in releaseReadLock() method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
     * Note: Not to be called on the EDT.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
    private void acquireReadLock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        assert ! SwingUtilities.isEventDispatchThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
        if (needReadLock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
                 * wait until all the EDT events are processed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
                 * some of the document changes are asynchronous
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
                 * we need to make sure we get the lock after those changes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
                SwingUtilities.invokeAndWait(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
                    new Runnable() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
                        public void run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
                    });
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            } catch (InterruptedException ignore) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
            } catch (java.lang.reflect.InvocationTargetException ignore) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            Document document = textComponentToPrint.getDocument();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            ((AbstractDocument) document).readLock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            needReadLock = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
     * Prepares {@code printShell} for printing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
     * Sets properties from the component to print.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
     * Sets width and FontRenderContext.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
     * Triggers Views creation for the printShell.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
     * There are two parts in the implementation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
     * First part (layout) is to be called on the printing thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
     * Second part (layoutOnEDT) is to be called on the EDT only.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
     * {@code layout} triggers {@code layoutOnEDT}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
     * @param width width to layout the text for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
    private void layout(final int width) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        if (!SwingUtilities.isEventDispatchThread()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
            Callable<Object> doLayoutOnEDT = new Callable<Object>() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
                public Object call() throws Exception {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
                    layoutOnEDT(width);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
            };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
            FutureTask<Object> futureLayoutOnEDT = new FutureTask<Object>(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
                doLayoutOnEDT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
             * We need to release document's readlock while printShell is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
             * initializing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
            releaseReadLock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
            SwingUtilities.invokeLater(futureLayoutOnEDT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
                futureLayoutOnEDT.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
            } catch (InterruptedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
                throw new RuntimeException(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
            } catch (ExecutionException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
                Throwable cause = e.getCause();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
                if (cause instanceof RuntimeException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
                    throw (RuntimeException) cause;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
                } else if (cause instanceof Error) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
                    throw (Error) cause;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
                    throw new RuntimeException(cause);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
            } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
                acquireReadLock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
            layoutOnEDT(width);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
        isLayouted = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
     * The EDT part of layout method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
     * This method is to be called on the EDT only.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
    private void layoutOnEDT(final int width) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
        assert SwingUtilities.isEventDispatchThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
        //need to have big value but smaller than MAX_VALUE otherwise
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        //printing goes south due to overflow somewhere
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
        final int HUGE_INTEGER = Integer.MAX_VALUE - 1000;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
        CellRendererPane rendererPane = new CellRendererPane();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
        //need to use JViewport since text is layouted to the viewPort width
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
        //otherwise it will be layouted to the maximum text width
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
        JViewport viewport = new JViewport();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        viewport.setBorder(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
        Dimension size = new Dimension(width, HUGE_INTEGER);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
        //JTextField is a special case
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
        //it layouts text in the middle by Y
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
        if (printShell instanceof JTextField) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
            size =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                new Dimension(size.width, printShell.getPreferredSize().height);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
        printShell.setSize(size);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
        viewport.setComponentOrientation(printShell.getComponentOrientation());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
        viewport.setSize(size);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
        viewport.add(printShell);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
        rendererPane.add(viewport);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
     * Calculates pageMetrics for the pages up to the {@code pageIndex} using
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
     * {@code rowsMetrics}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
     * Metrics are stored in the {@code pagesMetrics}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
     * @param pageIndex the page to update the metrics for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
     * @param pageHeight the page height
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
    private void updatePagesMetrics(final int pageIndex, final int pageHeight) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
        while (pageIndex >= pagesMetrics.size() && !rowsMetrics.isEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
            // add one page to the pageMetrics
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
            int lastPage = pagesMetrics.size() - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
            int pageStart = (lastPage >= 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
               ? pagesMetrics.get(lastPage).end + 1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
               : 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
            int rowIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
            for (rowIndex = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
                   rowIndex < rowsMetrics.size()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
                   && (rowsMetrics.get(rowIndex).end - pageStart + 1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
                     <= pageHeight;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
                   rowIndex++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
            if (rowIndex == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
                // can not fit a single row
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
                // need to split
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                pagesMetrics.add(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
                    new IntegerSegment(pageStart, pageStart + pageHeight - 1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                rowIndex--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
                pagesMetrics.add(new IntegerSegment(pageStart,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
                    rowsMetrics.get(rowIndex).end));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
                for (int i = 0; i <= rowIndex; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
                    rowsMetrics.remove(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
     * Calculates rowsMetrics for the document. The result is stored
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
     * in the {@code rowsMetrics}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
     * Two steps process.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
     * First step is to find yStart and yEnd for the every document position.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
     * Second step is to merge all intersected segments ( [yStart, yEnd] ).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
     */
42216
621af0ebf6c4 8169518: Suppress Deprecation warnings for deprecated Swing APIs
prr
parents: 30948
diff changeset
   756
    @SuppressWarnings("deprecation")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
    private void calculateRowsMetrics() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
        final int documentLength = printShell.getDocument().getLength();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
        List<IntegerSegment> documentMetrics = new ArrayList<IntegerSegment>(LIST_SIZE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
        Rectangle rect;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
        for (int i = 0, previousY = -1, previousHeight = -1; i < documentLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                 i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
                rect = printShell.modelToView(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
                if (rect != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
                    int y = (int) rect.getY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
                    int height = (int) rect.getHeight();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
                    if (height != 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
                            && (y != previousY || height != previousHeight)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
                         * we do not store the same value as previous. in our
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
                         * documents it is often for consequent positons to have
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
                         * the same modelToView y and height.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
                        previousY = y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
                        previousHeight = height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
                        documentMetrics.add(new IntegerSegment(y, y + height - 1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
            } catch (BadLocationException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
                assert false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
         * Merge all intersected segments.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
        Collections.sort(documentMetrics);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
        int yStart = Integer.MIN_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
        int yEnd = Integer.MIN_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
        for (IntegerSegment segment : documentMetrics) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
            if (yEnd < segment.start) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
                if (yEnd != Integer.MIN_VALUE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
                    rowsMetrics.add(new IntegerSegment(yStart, yEnd));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
                yStart = segment.start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
                yEnd = segment.end;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
                yEnd = segment.end;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
        if (yEnd != Integer.MIN_VALUE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
            rowsMetrics.add(new IntegerSegment(yStart, yEnd));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
     *  Class to represent segment of integers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
     *  we do not call it Segment to avoid confusion with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
     *  javax.swing.text.Segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
    private static class IntegerSegment implements Comparable<IntegerSegment> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
        final int start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        final int end;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
        IntegerSegment(int start, int end) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
            this.start = start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
            this.end = end;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
        public int compareTo(IntegerSegment object) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
            int startsDelta = start - object.start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
            return (startsDelta != 0) ? startsDelta : end - object.end;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
        @Override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
        public boolean equals(Object obj) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
            if (obj instanceof IntegerSegment) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
                return compareTo((IntegerSegment) obj) == 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
        @Override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
        public int hashCode() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
            // from the "Effective Java: Programming Language Guide"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
            int result = 17;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
            result = 37 * result + start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
            result = 37 * result + end;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
            return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
        @Override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
        public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
            return "IntegerSegment [" + start + ", " + end + "]";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
}