Articles Projects Tips Downloads Contacts About

Pagination in the JEditorPane/JTextPane. Part II (Printing)
By Stanislav Lapitsky

This article continues WYSIWYGpagination features implementation. After pagination is done as described in previous article we would like to print all the result pages. For multi paged printing in java we have to implement all the methods of Printable and Pageable interfaces.

PaginationPrinter class creating.

Thus the first step is defining PaginationPrinter class. The constructor has two parameters: PageFormat to specify printed page parameters and JEditorPane component to print. We store the parameters in class fields. They will be used later. If the JEditorPaneís kit is instance of PageableEditorKit class we have to set necessary attributes to perform content layout according to specified by PageFormat parameters. We set page width/height and margins of the kit then revalidate JEditorPane to invoke relayout with the new page format.

    public PaginationPrinter(PageFormat pageFormat, JEditorPane pane) {
        this.pageFormat = pageFormat;
        this.editorPane = pane;

        if (pane.getEditorKit() instanceof PageableEditorKit) {
            isPaginated = true;

            kit = (PageableEditorKit) pane.getEditorKit();
            kit.setPageWidth( (int) pageFormat.getWidth() + PageableEditorKit.DRAW_PAGE_INSET * 2);
            kit.setPageHeight( (int) pageFormat.getHeight() + PageableEditorKit.DRAW_PAGE_INSET * 2);
            int top = (int) pageFormat.getImageableY();
            int left = (int) pageFormat.getImageableX();
            int bottom = (int) (pageFormat.getHeight() - pageFormat.getImageableHeight() - top);
            int right = (int) (pageFormat.getWidth() - pageFormat.getImageableWidth() - left);
            kit.setPageMargins(new Insets(top, left, bottom, right));

            pane.revalidate();
        }
    }

Methods of Pageable are easy to implement. We need an additional collateral method to obtain number of pages from SectionView of the WYSIWYG JEditorPane. We extract the view from UI view hierarchy set of the JEditorPane instance. The first child of root view is our pageable SectionView from kit implementation.

    public int getPageCount() {
        if (isPaginated) {
            return ( (SectionView) editorPane.getUI().getRootView(editorPane).getView(0)).getPageCount();
        }
        return 1;
    }

    public int getNumberOfPages() {
        return getPageCount();
    }

    public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {
        return pageFormat;
    }

    public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException {
        return this;
    }

Implementation of print() method.

The most of work is done in the print() method. For each page (specified by pageIndex parameter) we translate visible range of the JEditorPane to be painted on page and shift a bit to hide page frame. Then just call printAll() method of JEditorPane to paint desired fragment on the graphics.

To increase painting speed we restrict painted area by setting clip region for specified page. The old clip region is saved and restored after painting.

    public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
        Graphics2D g2d = (Graphics2D) g;
        if (isPaginated) {
            g2d.translate(0, -kit.getPageHeight() * pageIndex);
            
            g2d.translate( -PageableEditorKit.DRAW_PAGE_INSET, -PageableEditorKit.DRAW_PAGE_INSET);
            Shape oldClip=g2d.getClip();
            
            g2d.setClip(0,kit.getPageHeight() * pageIndex,kit.getPageWidth(), kit.getPageHeight());
            editorPane.printAll(g2d);
            
            g2d.setClip(oldClip);
            if (pageIndex < getPageCount()) {
                return PAGE_EXISTS;
            }
        }
        else {
            if (pageIndex == 0) {
                g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
                editorPane.printAll(g);
                return PAGE_EXISTS;
            }
        }
        return NO_SUCH_PAGE;
    }

The PaginationPrinter class can be used to print JEditorPane without PageableEditorKit. But in this case all content will be printed on one page. If there is more text that can fit on one page all the rest content will be truncated.

Appendix

Here is the full source code of the pagination printing example.

Back to Table of Content