Package nl.siegmann.epublib.viewer

Source Code of nl.siegmann.epublib.viewer.ContentPane

package nl.siegmann.epublib.viewer;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;

import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

import nl.siegmann.epublib.Constants;
import nl.siegmann.epublib.browsersupport.NavigationEvent;
import nl.siegmann.epublib.browsersupport.NavigationEventListener;
import nl.siegmann.epublib.browsersupport.Navigator;
import nl.siegmann.epublib.domain.Book;
import nl.siegmann.epublib.domain.Resource;
import nl.siegmann.epublib.util.DesktopUtil;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Displays a page
*
*/
public class ContentPane extends JPanel implements NavigationEventListener,
    HyperlinkListener {

  private static final long serialVersionUID = -5322988066178102320L;

  private static final Logger log = LoggerFactory
      .getLogger(ContentPane.class);
  private Navigator navigator;
  private Resource currentResource;
  private JEditorPane editorPane;
  private JScrollPane scrollPane;
  private HTMLDocumentFactory htmlDocumentFactory;
 
  public ContentPane(Navigator navigator) {
    super(new GridLayout(1, 0));
    this.scrollPane = (JScrollPane) add(new JScrollPane());
    this.scrollPane.addKeyListener(new KeyListener() {
     
      @Override
      public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub
       
      }
     
      @Override
      public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub
       
      }
     
      @Override
      public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
          Point viewPosition = scrollPane.getViewport().getViewPosition();
          int newY = (int) (viewPosition.getY() + 10);
          scrollPane.getViewport().setViewPosition(new Point((int) viewPosition.getX(), newY));
        }
      }
    });
    this.scrollPane.addMouseWheelListener(new MouseWheelListener() {
     
      private boolean gotoNextPage = false;
      private boolean gotoPreviousPage = false;

      @Override
      public void mouseWheelMoved(MouseWheelEvent e) {
          int notches = e.getWheelRotation();
          int increment = scrollPane.getVerticalScrollBar().getUnitIncrement(1);
          if (notches < 0) {
          Point viewPosition = scrollPane.getViewport().getViewPosition();
          if (viewPosition.getY() - increment < 0) {
            if (gotoPreviousPage) {
              gotoPreviousPage = false;
              ContentPane.this.navigator.gotoPreviousSpineSection(-1, ContentPane.this);
            } else {
              gotoPreviousPage = true;
              scrollPane.getViewport().setViewPosition(new Point((int) viewPosition.getX(), 0));
            }
          }
          } else {
            // only move to the next page if we are exactly at the bottom of the current page
            Point viewPosition = scrollPane.getViewport().getViewPosition();
          int viewportHeight = scrollPane.getViewport().getHeight();
          int scrollMax = scrollPane.getVerticalScrollBar().getMaximum();
          if (viewPosition.getY() + viewportHeight + increment > scrollMax) {
            if (gotoNextPage) {
              gotoNextPage = false;
              ContentPane.this.navigator.gotoNextSpineSection(ContentPane.this);
            } else {
              gotoNextPage = true;
              int newY = scrollMax - viewportHeight;
              scrollPane.getViewport().setViewPosition(new Point((int) viewPosition.getX(), newY));
            }
          }
          }
        }
    });
    this.navigator = navigator;
    navigator.addNavigationEventListener(this);
    this.editorPane = createJEditorPane();
    scrollPane.getViewport().add(editorPane);
    this.htmlDocumentFactory = new HTMLDocumentFactory(navigator, editorPane.getEditorKit());
    initBook(navigator.getBook());
  }

  private void initBook(Book book) {
    if (book == null) {
      return;
    }
    htmlDocumentFactory.init(book);
    displayPage(book.getCoverPage());
  }
 
 
 
  /**
   * Whether the given searchString matches any of the possibleValues.
   *
   * @param searchString
   * @param possibleValues
   * @return Whether the given searchString matches any of the possibleValues.
   */
  private static boolean matchesAny(String searchString, String... possibleValues) {
    for (int i = 0; i < possibleValues.length; i++) {
      String attributeValue = possibleValues[i];
      if (StringUtils.isNotBlank(attributeValue) && (attributeValue.equals(searchString))) {
        return true;
      }
    }
    return false;
  }
 
 
  /**
   * Scrolls the editorPane to the startOffset of the current element in the elementIterator
   *
   * @param requestFragmentId
   * @param attributeValue
   * @param editorPane
   * @param elementIterator
   *
   * @return whether it was a match and we jumped there.
   */
  private static void scrollToElement(JEditorPane editorPane, HTMLDocument.Iterator elementIterator) {
    try {
      Rectangle rectangle = editorPane.modelToView(elementIterator.getStartOffset());
      if (rectangle == null) {
        return;
      }
      // the view is visible, scroll it to the
      // center of the current visible area.
      Rectangle visibleRectangle = editorPane.getVisibleRect();
      // r.y -= (vis.height / 2);
      rectangle.height = visibleRectangle.height;
      editorPane.scrollRectToVisible(rectangle);
    } catch (BadLocationException e) {
      log.error(e.getMessage());
    }
  }
 
 
  /**
   * Scrolls the editorPane to the first anchor element whose id or name matches the given fragmentId.
   *
   * @param fragmentId
   */
  private void scrollToNamedAnchor(String fragmentId) {
    HTMLDocument doc = (HTMLDocument) editorPane.getDocument();
    for (HTMLDocument.Iterator iter = doc.getIterator(HTML.Tag.A); iter.isValid(); iter.next()) {
      AttributeSet attributes = iter.getAttributes();
      if (matchesAny(fragmentId, (String) attributes.getAttribute(HTML.Attribute.NAME),
          (String) attributes.getAttribute(HTML.Attribute.ID))) {
        scrollToElement(editorPane, iter);
        break;
      }
    }
  }

  private JEditorPane createJEditorPane() {
    JEditorPane editorPane = new JEditorPane();
    editorPane.setBackground(Color.white);
    editorPane.setEditable(false);
    HTMLEditorKit htmlKit = new HTMLEditorKit();
    // StyleSheet myStyleSheet = new StyleSheet();
    // String normalTextStyle = "font-size: 12px, font-family: georgia";
    // myStyleSheet.addRule("body {" + normalTextStyle + "}");
    // myStyleSheet.addRule("p {" + normalTextStyle + "}");
    // myStyleSheet.addRule("div {" + normalTextStyle + "}");
    // htmlKit.setStyleSheet(myStyleSheet);
    editorPane.setEditorKit(htmlKit);
    editorPane.addHyperlinkListener(this);
    editorPane.addKeyListener(new KeyListener() {

      @Override
      public void keyTyped(KeyEvent keyEvent) {
      }

      @Override
      public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

      }

      @Override
      public void keyPressed(KeyEvent keyEvent) {
        if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
          navigator.gotoNextSpineSection(ContentPane.this);
        } else if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
          navigator.gotoPreviousSpineSection(ContentPane.this);
//        } else if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
//          ContentPane.this.gotoPreviousPage();
        } else if (keyEvent.getKeyCode() == KeyEvent.VK_SPACE) {
//          || (keyEvent.getKeyCode() == KeyEvent.VK_DOWN)) {
          ContentPane.this.gotoNextPage();
        }
      }
    });
    return editorPane;
  }

  public void displayPage(Resource resource) {
    displayPage(resource, 0);
  }

  public void displayPage(Resource resource, int sectionPos) {
    if (resource == null) {
      return;
    }
    try {
      HTMLDocument document = htmlDocumentFactory.getDocument(resource);
      if (document == null) {
        return;
      }
      currentResource = resource;
      editorPane.setDocument(document);
      scrollToCurrentPosition(sectionPos);
    } catch (Exception e) {
      log.error("When reading resource " + resource.getId() + "("
          + resource.getHref() + ") :" + e.getMessage(), e);
    }
  }

  private void scrollToCurrentPosition(int sectionPos) {
    if (sectionPos < 0) {
      editorPane.setCaretPosition(editorPane.getDocument().getLength());
    } else {
      editorPane.setCaretPosition(sectionPos);
    }
    if (sectionPos == 0) {
      scrollPane.getViewport().setViewPosition(new Point(0, 0));
    } else if (sectionPos < 0) {
      int viewportHeight = scrollPane.getViewport().getHeight();
      int scrollMax = scrollPane.getVerticalScrollBar().getMaximum();
      scrollPane.getViewport().setViewPosition(new Point(0, scrollMax - viewportHeight));
    }
  }

  public void hyperlinkUpdate(HyperlinkEvent event) {
    if (event.getEventType() != HyperlinkEvent.EventType.ACTIVATED) {
      return;
    }
        final URL url = event.getURL();
        if (url.getProtocol().toLowerCase().startsWith("http") && !"".equals(url.getHost())) {
            try {
                DesktopUtil.launchBrowser(event.getURL());
                return;
            } catch (DesktopUtil.BrowserLaunchException ex) {
                log.warn("Couldn't launch system web browser.", ex);
            }
        }
    String resourceHref = calculateTargetHref(event.getURL());
    if (resourceHref.startsWith("#")) {
      scrollToNamedAnchor(resourceHref.substring(1));
      return;
    }

    Resource resource = navigator.getBook().getResources().getByHref(resourceHref);
    if (resource == null) {
      log.error("Resource with url " + resourceHref + " not found");
    } else {
      navigator.gotoResource(resource, this);
    }
  }

  public void gotoPreviousPage() {
    Point viewPosition = scrollPane.getViewport().getViewPosition();
    if (viewPosition.getY() <= 0) {
      navigator.gotoPreviousSpineSection(this);
      return;
    }
    int viewportHeight = scrollPane.getViewport().getHeight();
    int newY = (int) viewPosition.getY();
    newY -= viewportHeight;
    newY = Math.max(0, newY - viewportHeight);
    scrollPane.getViewport().setViewPosition(
        new Point((int) viewPosition.getX(), newY));
  }

  public void gotoNextPage() {
    Point viewPosition = scrollPane.getViewport().getViewPosition();
    int viewportHeight = scrollPane.getViewport().getHeight();
    int scrollMax = scrollPane.getVerticalScrollBar().getMaximum();
    if (viewPosition.getY() + viewportHeight >= scrollMax) {
      navigator.gotoNextSpineSection(this);
      return;
    }
    int newY = ((int) viewPosition.getY()) + viewportHeight;
    scrollPane.getViewport().setViewPosition(
        new Point((int) viewPosition.getX(), newY));
  }

 
  /**
   * Transforms a link generated by a click on a link in a document to a resource href.
   * Property handles http encoded spaces and such.
   *
   * @param clickUrl
   * @return a link generated by a click on a link transformed into a document to a resource href.
   */
  private String calculateTargetHref(URL clickUrl) {
    String resourceHref = clickUrl.toString();
    try {
      resourceHref = URLDecoder.decode(resourceHref,
          Constants.CHARACTER_ENCODING);
    } catch (UnsupportedEncodingException e) {
      log.error(e.getMessage());
    }
    resourceHref = resourceHref.substring(ImageLoaderCache.IMAGE_URL_PREFIX
        .length());

    if (resourceHref.startsWith("#")) {
      return resourceHref;
    }
    if (currentResource != null
        && StringUtils.isNotBlank(currentResource.getHref())) {
      int lastSlashPos = currentResource.getHref().lastIndexOf('/');
      if (lastSlashPos >= 0) {
        resourceHref = currentResource.getHref().substring(0,
            lastSlashPos + 1)
            + resourceHref;
      }
    }
    return resourceHref;
  }

 
  public void navigationPerformed(NavigationEvent navigationEvent) {
    if (navigationEvent.isBookChanged()) {
      initBook(navigationEvent.getCurrentBook());
    } else {
      if (navigationEvent.isResourceChanged()) {
      displayPage(navigationEvent.getCurrentResource(),
          navigationEvent.getCurrentSectionPos());
      } else if (navigationEvent.isSectionPosChanged()) {
        editorPane.setCaretPosition(navigationEvent.getCurrentSectionPos());
      }
      if (StringUtils.isNotBlank(navigationEvent.getCurrentFragmentId())) {
        scrollToNamedAnchor(navigationEvent.getCurrentFragmentId());
      }
    }
  }


}
TOP

Related Classes of nl.siegmann.epublib.viewer.ContentPane

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.