OSDN Git Service

Change directory structure.
[dvibrowser/dvi2epub.git] / src / main / java / jp / sourceforge / dvibrowser / dvicore / gui / swing / TDviPage.java
diff --git a/src/main/java/jp/sourceforge/dvibrowser/dvicore/gui/swing/TDviPage.java b/src/main/java/jp/sourceforge/dvibrowser/dvicore/gui/swing/TDviPage.java
new file mode 100644 (file)
index 0000000..b4f4804
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2009, Takeyuki Nagao
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the
+ * following conditions are met:
+ * 
+ *  * Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer in the documentation and/or other
+ *    materials provided with the distribution.
+ *    
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+package jp.sourceforge.dvibrowser.dvicore.gui.swing;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.logging.Logger;
+
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.EventListenerList;
+
+import jp.sourceforge.dvibrowser.dvicore.DviException;
+import jp.sourceforge.dvibrowser.dvicore.DviRect;
+import jp.sourceforge.dvibrowser.dvicore.api.DviContext;
+import jp.sourceforge.dvibrowser.dvicore.api.DviContextSupport;
+import jp.sourceforge.dvibrowser.dvicore.api.DviPage;
+import jp.sourceforge.dvibrowser.dvicore.ctx.DviToolkit;
+import jp.sourceforge.dvibrowser.dvicore.util.DaemonThreadFactory;
+
+
+public class TDviPage extends JPanel implements DviContextSupport, ChangeListener
+{
+  private static final Logger LOGGER = Logger.getLogger(TDviPage.class.getName());
+  private static final long serialVersionUID = -7167678585159838308L;
+  
+  private boolean busy = false;
+  
+  private final DviContextSupport dcs;
+  public DviContext getDviContext() { return dcs.getDviContext(); }
+
+  public TDviPage(DviContextSupport dcs, DviPage page) {
+    super();
+    this.dcs = dcs;
+    this.viewSpec = new ViewSpec(this);
+    this.viewSpec.setResolution(viewSpec.getResolution().approximate(200));
+    setPage(page);
+  }
+  
+  public TDviPage(DviContextSupport dcs) {
+    this(dcs, null);
+  }
+
+  private DviPage page = null;
+
+  public void setPage(DviPage page)
+  {
+    this.page = page;
+    determineSize();
+  }
+  
+  public DviPage getPage() { return page; }
+
+  private ViewSpec viewSpec;
+
+  public void setViewSpec(ViewSpec viewSpec)
+  {
+    LOGGER.fine("page=" + page + ",viewSpec=" + viewSpec);
+    this.viewSpec = viewSpec;
+    determineSize();
+  }
+  
+  public ViewSpec getViewSpec() { return viewSpec; }
+
+//  private DviRect bbox;
+//
+//  public void setBoundingBox(DviRect bbox)
+//  {
+//    this.bbox = bbox;
+//    determineSize();
+//  }
+//
+//  public DviRect getBoundingBox()
+//  {
+//    return bbox;
+//  }
+
+//  private Anchor.Href myHref = null;
+//  private DviRect saveBBOX = null;
+//
+//  public ByteRange getByteRangeFor(DviRect rect)
+//  {
+//    try {
+//      DviResolution res = viewSpec.getResolution();
+//
+//      rect = rect.intersect(displayRect);
+//      if (rect.isEmpty())
+//        return null;
+//      rect = rect.magnify(res.shrinkFactor());
+//
+//      Geometer geometer = new BasicGeometer(this);
+//      ByteRangeComputer brc = new ByteRangeComputer(this, res, rect);
+//      geometer.setPainter(brc);
+//      getDviContext().execute(page, geometer);
+//      AnchorSet anchors = (AnchorSet) rsc.getDataSource().find(AnchorSet.class,
+//          page);
+//      if (myHref != null) {
+//        anchors.remove(myHref);
+//      }
+//      ByteRange br = brc.getByteRange();
+//      anchors.add(myHref = new Anchor.Href(br.begin(), br.end(), "none"));
+//      if (saveBBOX != null) {
+//        DviRect r = saveBBOX;
+//        repaint(r.x(), r.y(), r.width(), r.height());
+//      }
+//      DviRect r = brc.getBounds().shrink(res.shrinkFactor());
+//      repaint(r.x(), r.y(), r.width(), r.height());
+//      saveBBOX = r;
+//      return br;
+//    } catch (DviException ex) {
+//      Logger.trace(ex);
+//      return null;
+//    }
+//  }
+
+  private DviRect displayRect = null;
+
+  public void determineSize()
+  {
+    final DviToolkit utils = getDviContext().getDviToolkit();
+    displayRect = null;
+    try {
+      if (layout != null)
+        displayRect = layout.determinePageSize(this);
+    } catch (Exception e) {
+      LOGGER.severe(e.toString());
+      e.printStackTrace();
+    }
+    if (displayRect == null) {
+      displayRect = utils.computePageBoundingBox
+        (viewSpec.getPaperSize(), viewSpec.getResolution());
+    }
+
+    setPreferredSize(new Dimension(displayRect.width(), displayRect.height()));
+    setSize(new Dimension(displayRect.width(), displayRect.height()));
+    revalidate();
+  }
+  
+  private static ExecutorService exe = Executors.newFixedThreadPool(3, new DaemonThreadFactory());
+  
+  protected ExecutorService getExecutorService()
+  {
+    return exe;
+  }
+  
+  protected void startPagePreparation(Graphics g, final Rectangle rect, final DviPage page, final ViewSpec viewSpec)
+  {
+    final DviToolkit utils = getDviContext().getDviToolkit();
+
+    LOGGER.finer("Preparing page for paint: " + page);
+    getExecutorService().submit(new Runnable() {
+      public void run()
+      {
+        try {
+          utils.prepareForRendering(page, viewSpec);
+        } catch (Exception e) {
+          LOGGER.warning(e.toString());
+        }
+        SwingUtilities.invokeLater(new Runnable() {
+          public void run()
+          {
+            setBusy(false);
+            repaint();
+          }
+        });
+      }
+    });
+    setBusy(true);
+    paintDummyContents(g, rect, viewSpec);
+  }
+
+  private void paintDummyContents(Graphics g, final Rectangle rect,
+      final ViewSpec viewSpec)
+  {
+    g.setColor(viewSpec.getBackgroundColor().toColor());
+    g.fillRect(rect.x, rect.y, rect.width, rect.height);
+  }
+  
+  protected void paintComponent(Graphics g)
+  {
+    super.paintComponent(g);
+
+    final DviToolkit utils = getDviContext().getDviToolkit();
+    
+    if (page == null) return;
+    
+    final Rectangle rect = g.getClipBounds();
+    g.fillRect(rect.x, rect.y, rect.width, rect.height);
+
+    boolean enableDelayedRendering = true;
+    
+    try {
+      enableDelayedRendering = getEnableDelayedRendering();
+    } catch (DviException e1) {
+      LOGGER.warning(e1.toString());
+    }
+    
+    if (enableDelayedRendering) {
+      if (!utils.canRenderPageImmediately(page, viewSpec)) {
+        LOGGER.finest("delayed rendering");
+        startPagePreparation(g, rect, page, viewSpec);
+        return;
+      }
+    }
+    
+    try {
+      LOGGER.finest("rendering page=" + page.getPageNumber() + " rect=" + rect + " viewSpec=" + viewSpec);
+//      DviRect targetArea = new DviRect
+//        (rect.x + displayRect.x(), rect.y + displayRect.y(), rect.width+1, rect.height+1);
+      DviRect targetArea = DviRect.fromRectangle(rect).translate(displayRect.topLeft());
+      if (!targetArea.isEmpty()) {
+          BufferedImage img = utils.renderToBufferedImage(page, targetArea, viewSpec);
+          g.drawImage(img, rect.x, rect.y, null);
+      }
+    } catch (DviException e) {
+      LOGGER.warning(e.toString());
+      e.printStackTrace();
+      paintDummyContents(g, rect, viewSpec);
+    }
+  }
+  
+  public void stateChanged(ChangeEvent e)
+  {
+    LOGGER.fine("stateChanged called: EDT=" + SwingUtilities.isEventDispatchThread());
+    SwingUtilities.invokeLater(new Runnable() {
+      public void run()
+      {
+        determineSize();
+        revalidate();
+        repaint();
+      }
+    });
+  }
+  
+  private DviLayoutManager layout = new DefaultDviLayoutManager(this, 1);
+  
+  public boolean getEnableDelayedRendering()
+  throws DviException
+  {
+    if (layout == null) return true;
+    return layout.getEnableDelayedRendering(this);
+  }
+
+  public DviLayoutManager getDviLayout()
+  {
+    return layout;
+  }
+
+  public void setDviLayout(DviLayoutManager layout)
+  {
+    if (layout == null)
+      throw new NullPointerException("layout");
+    this.layout = layout;
+  }
+
+  protected void setBusy(boolean busy) {
+    this.busy = busy;
+    fireChangeEvent();
+  }
+
+  public boolean isBusy() {
+    return busy;
+  }
+  
+  protected EventListenerList listenerList = new EventListenerList();
+
+  public void addChangeListener(ChangeListener l)
+  {
+      listenerList.add(ChangeListener.class, l);
+  }
+
+  public void removeChangeListener(ChangeListener l)
+  {
+      listenerList.remove(ChangeListener.class, l);
+  }
+
+  protected void fireChangeEvent()
+  {
+    ChangeEvent event = null;
+    
+    Object[] listeners = listenerList.getListenerList();
+    for (int i = listeners.length-2; i>=0; i-=2) {
+      if (listeners[i] == ChangeListener.class) {
+        if (event == null)
+          event = new ChangeEvent(this);
+        ((ChangeListener)listeners[i+1]).stateChanged(event);
+      }
+    }
+  }
+
+}