If you have a customized xhtml variant, like evernote ENML format and you want to render it with Flying Saucer R8 you must first make sure that the extra element (in ENML case, en-media) is defined as a block-level element. To do that you create your own NamespaceHandler and you make sure that you return "display: block;" for en-media in the implementation of NamespaceHandler.getNonCssStyling. (See ENMLNamespaceHandler.java below)
....
XHTMLPanel panel = new XHTMLPanel();
panel.setDocument(doc,"",new ENMLNamespaceHandler(new XhtmlNamespaceHandler()));
....
class ENMLNamespaceHandler implements NamespaceHandler {
....
public String getNonCssStyling(Element e) {
String toReturn = delegate.getNonCssStyling(e);
if ("en-media".equalsIgnoreCase(e.getNodeName())) {
toReturn = "display: block;";
}
return toReturn;
}
....
}With that you ensure that xhtmlrenderer will call ReplacedElementFactory.createReplacedElement for en-media. Now you must supply a ReplacedElementFactory that it’s able to process en-media. Usually the implementation of the createReplacedElement() involves creating a Swing JComponent, wrapping it in a SwingReplacedElement and adding it to the LayoutContext.getCanvas().
....
ReplacedElementFactory cef = new ENMLReplacedElementFactory(new SwingReplacedElementFactory());
XHTMLPanel panel = new XHTMLPanel();
panel.getSharedContext().setReplacedElementFactory(cef);
panel.setDocument(doc,"",new ENMLNamespaceHandler(new XhtmlNamespaceHandler()));
....
public class ENMLReplacedElementFactory implements ReplacedElementFactory {
...
public ReplacedElement createReplacedElement(LayoutContext context, BlockBox box,
UserAgentCallback uac, int cssWidth, int cssHeight)
{
if ("en-media".equals(box.getElement().getNodeName())) {
JTextArea cc = new JTextArea();
cc.setText("Missing implementation for en-media");
cc.setSize(cc.getPreferredSize());
context.getCanvas().add(cc);
ReplacedElement toReturn = new SwingReplacedElement(cc) {
public boolean isRequiresInteractivePaint() {
return false;
}
};
return toReturn;
}
ReplacedElement toReturn = delegate.createReplacedElement(context, box, uac, cssWidth, cssHeight);
return toReturn;
}
....
}References:
- Experiment: embedding Flash in Flying Saucer
- NamespaceHandler
- ReplacedElementFactory
- Re: custom layout support
- http://wiki.java.net/bin/view/Javadesktop/TheFlyingSaucerInProcessFAQ
ENMLNamespaceHandler.java:
package com.rubenlaguna.en4j.NoteContentViewModule; import java.util.logging.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xhtmlrenderer.css.extend.StylesheetFactory; import org.xhtmlrenderer.css.sheet.StylesheetInfo; import org.xhtmlrenderer.extend.NamespaceHandler; /** * * @author ecerulm */ class ENMLNamespaceHandler implements NamespaceHandler { private final NamespaceHandler delegate; public ENMLNamespaceHandler(NamespaceHandler h) { this.delegate = h; } public boolean isImageElement(Element e) { return delegate.isImageElement(e); } public boolean isFormElement(Element e) { return delegate.isFormElement(e); } public StylesheetInfo[] getStylesheets(Document doc) { return delegate.getStylesheets(doc); } public String getNonCssStyling(Element e) { String toReturn = delegate.getNonCssStyling(e); if ("en-media".equalsIgnoreCase(e.getNodeName())) { toReturn = "display: block;"; } Logger.getLogger(ENMLNamespaceHandler.class.getName()).info("style for ("+e.getNodeName()+") is ("+toReturn+")"); return toReturn; } public String getNamespace() { return delegate.getNamespace(); } public String getLinkUri(Element e) { return delegate.getLinkUri(e); } public String getLang(Element e) { return delegate.getLang(e); } public String getImageSourceURI(Element e) { return delegate.getImageSourceURI(e); } public String getID(Element e) { return delegate.getID(e); } public String getElementStyling(Element e) { return delegate.getElementStyling(e); } public String getDocumentTitle(Document doc) { return delegate.getDocumentTitle(doc); } public StylesheetInfo getDefaultStylesheet(StylesheetFactory factory) { return delegate.getDefaultStylesheet(factory); } public String getClass(Element e) { return delegate.getClass(e); } public String getAttributeValue(Element e, String namespaceURI, String attrName) { return delegate.getAttributeValue(e, namespaceURI, attrName); } public String getAttributeValue(Element e, String attrName) { return delegate.getAttributeValue(e, attrName); } public String getAnchorName(Element e) { return delegate.getAnchorName(e); } }
ENMLReplacedElementFactory.java:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.rubenlaguna.en4j.NoteContentViewModule; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextArea; import org.w3c.dom.Element; import org.xhtmlrenderer.extend.ReplacedElement; import org.xhtmlrenderer.extend.ReplacedElementFactory; import org.xhtmlrenderer.extend.UserAgentCallback; import org.xhtmlrenderer.layout.LayoutContext; import org.xhtmlrenderer.render.BlockBox; import org.xhtmlrenderer.simple.extend.FormSubmissionListener; import org.xhtmlrenderer.swing.EmptyReplacedElement; import org.xhtmlrenderer.swing.ImageReplacedElement; import org.xhtmlrenderer.swing.SwingReplacedElement; import org.xhtmlrenderer.swing.SwingReplacedElementFactory; import org.xhtmlrenderer.util.ImageUtil; /** * * @author ecerulm */ class ENMLReplacedElementFactory implements ReplacedElementFactory { private final SwingReplacedElementFactory delegate; private final Logger LOG = Logger.getLogger(ENMLReplacedElementFactory.class.getName()); public ENMLReplacedElementFactory(SwingReplacedElementFactory delegate) { this.delegate = delegate; } public void setFormSubmissionListener(FormSubmissionListener fsl) { delegate.setFormSubmissionListener(fsl); } public void reset() { delegate.reset(); } public void remove(Element e) { delegate.remove(e); } public ReplacedElement createReplacedElement(LayoutContext context, BlockBox box, UserAgentCallback uac, int cssWidth, int cssHeight) { ReplacedElement toReturn = null; Logger.getLogger(ENMLReplacedElementFactory.class.getName()).log(Level.INFO, "Element:" + box.getElement().getNodeName()); Logger.getLogger(ENMLReplacedElementFactory.class.getName()).log(Level.INFO, "Element content:" + box.getElement().getNodeValue()); if ("en-media".equals(box.getElement().getNodeName())) { //if("image/jpeg".equalsIgnoreCase(box.getElement().getAttribute("type"))){ // // toReturn = loadImage() // return toReturn; //} toReturn = brokenImage(context, 100, 100); } if (null == toReturn) { toReturn = delegate.createReplacedElement(context, box, uac, cssWidth, cssHeight); } return toReturn; } private ReplacedElement brokenImage(LayoutContext context, int cssWidth, int cssHeight) { //TODO: add a real implementation that returns an image ReplacedElement toReturn = null; JTextArea cc = new JTextArea(); cc.setText("Missing implementation for en-media"); //cc.setPreferredSize(new Dimension(cssWidth, cssHeight)); cc.setSize(cc.getPreferredSize()); context.getCanvas().add(cc); toReturn = new SwingReplacedElement(cc) { public boolean isRequiresInteractivePaint() { return false; } }; return toReturn; } }





































