/* * Copyright 1999-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.fop.render.awt.viewer; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.util.EventListener; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JViewport; import javax.swing.SwingUtilities; import javax.swing.border.EmptyBorder; import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionEvent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.PageViewport; import org.apache.fop.fo.Constants; // import org.apache.fop.render.awt.AWTRenderer; import org.apache.fop.render.awt.AWTRenderer; /** Holds a scrollpane with the rendered page(s) and handles actions performed to alter the display of the page. Use PreviewPanel when you want to embed a preview in your own application with your own controls. Use PreviewDialog when you want to use the standard Fop controls. In order to embed a PreviewPanel in your own app, use the following:
FOUserAgent ua = new FOUserAgent(); ua.setRendererOverride(new AWTRenderer()); previewPanel = new PreviewPanel(ua);*/ public class PreviewPanel extends JPanel { /** Constant for setting single page display. */ public static final int SINGLE = 1; /** Constant for setting continuous page display. */ public static final int CONTINUOUS = 2; /** Constant for displaying even/odd pages side by side in continuous form. */ public static final int CONT_FACING = 3; /** The number of pixels left empty at the top bottom and sides of the page. */ private static final int BORDER_SPACING = 10; /** The main display area */ private JScrollPane previewArea; /** The AWT renderer - often shared with PreviewDialog */ private AWTRenderer renderer; /** The FOUserAgent associated with this panel - often shared with PreviewDialog */ protected FOUserAgent foUserAgent; /** The number of the page which is currently selected */ private int currentPage = 0; /** The index of the first page displayed on screen. */ private int firstPage = 0; /** The number of pages concurrently displayed on screen. */ private int pageRange = 1; /** The display mode. One of SINGLE, CONTINUOUS or CONT_FACING. */ private int displayMode = SINGLE; /** The component(s) that hold the rendered page(s) */ private ImageProxyPanel[] pagePanels = null; /** * Panel showing the page panels in a grid. Usually the dimensions * of the grid are 1x1, nx1 or nx2. */ private JPanel gridPanel = null; /** Asynchronous reloader thread, used when reload() method is called. */ private Reloader reloader; /** The Fop object used for refreshing/reloading the view */ protected Fop fop; /** * Allows any mouse drag on the page area to scroll the display window. */ private ViewportScroller scroller; public PreviewPanel(FOUserAgent foUserAgent, AWTRenderer renderer) { super(new GridLayout(1,1)); this.renderer = renderer; this.foUserAgent = foUserAgent; gridPanel = new JPanel(); gridPanel.setLayout(new GridLayout(0, 1)); // rows, cols previewArea = new JScrollPane(gridPanel); previewArea.getViewport().setBackground(Color.gray); // FIXME should add scroll wheel support here at some point. scroller = new ViewportScroller(previewArea.getViewport()); previewArea.addMouseListener(scroller); previewArea.addMouseMotionListener(scroller); previewArea.setMinimumSize(new Dimension(50, 50)); add(previewArea); } /** * Changes the current visible page */ public int getPage() { return currentPage; } /** Selects the given page, displays it on screen and notifies listeners about the change in selection. */ public void setPage(int number) { if (displayMode==CONTINUOUS || displayMode==CONT_FACING) { // FIXME Should scroll so page is visible currentPage = number; } else { // single page mode currentPage = number; firstPage = currentPage; } showPage(); } /** * Sets the display mode. * @param mode One of SINGLE, CONTINUOUS or CONT_FACING. */ public void setDisplayMode(int mode) { if (mode==displayMode) return; displayMode = mode; gridPanel.setLayout(new GridLayout(0, displayMode==CONT_FACING ? 2 : 1)); reload(); } /** * Returns the display mode. * @return mode One of SINGLE, CONTINUOUS or CONT_FACING. */ public int getDisplayMode() { return displayMode; } /** * Reloads and reformats document. */ public synchronized void reload() { if (reloader == null || !reloader.isAlive()) { reloader = new Reloader(); reloader.start(); } } /** * Allows a (yet) simple visual debug of the document. */ void debug(){ renderer.debug = !renderer.debug; reload(); } /** * Allows any mouse drag on the page area to scroll the display window. */ private class ViewportScroller implements MouseListener, MouseMotionListener { /** The viewport to be scrolled */ private final JViewport viewport; /** Starting position of a mouse drag - X co-ordinate */ private int startPosX = 0; /** Starting position of a mouse drag - Y co-ordinate */ private int startPosY = 0; ViewportScroller(JViewport vp) { viewport = vp; } // ***** MouseMotionListener ***** public synchronized void mouseDragged(MouseEvent e) { if (viewport==null) return; int x = e.getX(); int y = e.getY(); int xmove = x - startPosX; int ymove = y - startPosY; int viewWidth = viewport.getExtentSize().width; int viewHeight = viewport.getExtentSize().height; int imageWidth = viewport.getViewSize().width; int imageHeight = viewport.getViewSize().height; Point viewPoint = viewport.getViewPosition(); int viewX = Math.max(0, Math.min(imageWidth - viewWidth, viewPoint.x-xmove)); int viewY = Math.max(0, Math.min(imageHeight - viewHeight, viewPoint.y-ymove)); viewport.setViewPosition(new Point(viewX, viewY)); startPosX = x; startPosY = y; } public void mouseMoved(MouseEvent e) { } // ***** MouseListener ***** public void mousePressed(MouseEvent e) { startPosX = e.getX(); startPosY = e.getY(); } public void mouseExited(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } } /** * This class is used to reload document in a thread safe way. */ private class Reloader extends Thread { public void run() { if (!renderer.renderingDone) { // do not allow the reloading while FOP is still rendering JOptionPane.showMessageDialog(previewArea, "Cannot perform the requested operation until " + "all page are rendererd. Please wait", "Please wait ", 1 /* INFORMATION_MESSAGE */); return; } if (fop == null) { fop = new Fop(Constants.RENDER_AWT, foUserAgent); } pagePanels = null; int savedCurrentPage = currentPage; currentPage = 0; gridPanel.removeAll(); switch(displayMode) { case CONT_FACING: // This page intentionally left blank // Makes 0th/1st page on rhs gridPanel.add(new JLabel("")); case CONTINUOUS: currentPage = 0; firstPage = 0; pageRange = renderer.getNumberOfPages(); break; case SINGLE: default: currentPage = 0; firstPage = 0; pageRange = 1; break; } pagePanels = new ImageProxyPanel[pageRange]; for (int pg = 0;pg