/* Copyright (C) 2006 Christian Schneider
*
* This file is part of Nomad.
*
* Nomad is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Nomad is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Nomad; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.sf.nmedit.jtheme.store2;
import java.awt.Image;
import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import javax.swing.ImageIcon;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import net.sf.nmedit.jpatch.PModule;
import net.sf.nmedit.jpatch.PModuleDescriptor;
import net.sf.nmedit.jtheme.JTContext;
import net.sf.nmedit.jtheme.JTException;
import net.sf.nmedit.jtheme.component.JTComponent;
import net.sf.nmedit.jtheme.component.JTImage;
import net.sf.nmedit.jtheme.image.AbstractImageResource;
import net.sf.nmedit.jtheme.image.ImageResource;
import net.sf.nmedit.jtheme.image.SVGImageResource;
import net.sf.nmedit.jtheme.image.SVGStringRessource;
import net.sf.nmedit.jtheme.image.ToolkitImageResource;
import net.sf.nmedit.jtheme.store.DefaultStorageContext;
import net.sf.nmedit.jtheme.store.StorageContext;
import net.sf.nmedit.nmutils.graphics.GraphicsToolkit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.transform.JDOMSource;
public class ImageElement extends AbstractElement implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 1462274961082257283L;
private String src;
private String id;
private transient ImageResource imageResource; // TODO serialization
protected boolean reducible = false;
private static Log getLogger()
{
return LogFactory.getLog(ImageElement.class);
}
public void initializeElement(StorageContext context)
{
if (id != null)
{
imageResource = context.getCachedImage(id);
}
}
public static ImageResource getImageResource(StorageContext context, Element element)
{
String href = getXlinkHref(element);
if (href == null) return null;
ImageResource ir;
if (href.endsWith("svg"))
ir = new SVGImageResource(href, context.getContextClassLoader());
else
ir = new ToolkitImageResource(href, context.getContextClassLoader());
ir.setImageCache(context.getImageCache());
return ir;
}
private static final String SVG_NS = "http://www.w3.org/2000/svg";
private transient Namespace cachedSvgNameSpace;
private Namespace svgns()
{
if (cachedSvgNameSpace == null)
cachedSvgNameSpace = Namespace.getNamespace(SVG_NS);
return cachedSvgNameSpace;
}
private static final String XLINK_NS = "http://www.w3.org/1999/xlink";
private static Namespace xlinkns = Namespace.getNamespace(XLINK_NS);
public static String getXlinkHref(Element e)
{
return e.getAttributeValue("href", xlinkns);
}
public void renderImage(StorageContext context)
{
render();
}
private Image render()
{
if (imageResource == null)
return null;
Image image = imageResource.getImage(width, height);
if (image == null)
{
Log log = LogFactory.getLog(getClass());
if (log.isWarnEnabled())
log.warn("Could not open image [width="+width+",height="+height+"] from:"+imageResource);
return null;
}
return image;
}
@Override
public JTComponent createComponent(JTContext context,
PModuleDescriptor descriptor, PModule module) throws JTException
{
Image image = render();
if (image == null)
return null;
JTImage jtimg = (JTImage) context.createComponent(JTContext.TYPE_IMAGE);
setName(jtimg);
this.reducible = jtimg.isReducible();
jtimg.setIcon(new ImageIcon(image));
setLocation(jtimg);
if (width>=0 && height>=0)
{
setSize(jtimg);
}
else
{
jtimg.setSize(GraphicsToolkit.getImageSize(image));
}
return jtimg;
}
@Override
public boolean isReducible()
{
return reducible;
}
public static AbstractElement createElement(StorageContext context, Element element)
{
ImageElement e = new ImageElement();
e.initElement(context, element);
e.lookupImage(context, element);
return e;
}
private AbstractImageResource createResource(StorageContext context, String src)
{
AbstractImageResource ir;
if (src.endsWith(".svg"))
ir = new SVGImageResource(src, context.getContextClassLoader());
else
ir = new ToolkitImageResource(src, context.getContextClassLoader());
ir.setImageCache(context.getImageCache());
return ir;
}
@Override
protected void initAttributes(StorageContext context, Attribute att)
{
if ("href".equals(att.getName()) && xlinkns.equals(att.getNamespace()))
{
src = att.getValue();
}
else
{
super.initAttributes(context, att);
}
}
protected void lookupImage(StorageContext context, Element e)
{
if (imageResource != null)
return;
if (src != null)
{
if (context instanceof DefaultStorageContext)
{
DefaultStorageContext dsc = (DefaultStorageContext) context;
imageResource = dsc.getCachedImage(src);
if (src.startsWith("url(#") && src.endsWith(")"))
{
String id = src.substring(5, src.length()-1);
imageResource = dsc.getImageResourceById(id);
this.id = id;
}
else if (imageResource == null)
{
AbstractImageResource air = createResource(context, src);
imageResource = air;
imageResource.setImageCache(context.getImageCache());
this.id = air.getResolvedURL().toString();
dsc.putImage(id, air);
}
}
else
{
imageResource = createResource(context, src);
}
}
else
{
Element svg = e.getChild("svg", svgns());
if (svg != null)
{
imageResource = new SVGStringRessource(element2txt(svg));
imageResource.setImageCache(context.getImageCache());
if (context instanceof DefaultStorageContext)
{
DefaultStorageContext dsc = (DefaultStorageContext) context;
this.id = context.generateId();
dsc.putImage(id, imageResource);
}
}
}
}
public static Image getImage(String href, StorageContext context)
{
if (href.startsWith("url(#") && href.endsWith(")"))
{
if (context instanceof DefaultStorageContext)
{
DefaultStorageContext c = (DefaultStorageContext) context;
String id = href.substring(5, href.length()-1);
ImageResource ir = c.getImageResourceById(id);
return ir == null ? null : ir.getImage(-1, -1);
}
return null;
}
else return context.getImage(href);
}
public static ImageResource svgElement2img(Element element)
{
String svg = element2txt(element);
if (svg == null) return null;
return new SVGStringRessource(svg);
}
public static String element2txt(Element el)
{
TransformerFactory tf = TransformerFactory.newInstance();
// set all necessary features for your transformer -> see OutputKeys
Transformer t;
try
{
t = tf.newTransformer();
}
catch (TransformerConfigurationException e)
{
return null;
}
StringWriter sw = new StringWriter();
try
{
t.transform(new JDOMSource(el), new StreamResult(sw));
}
catch (TransformerException e)
{
Log log = getLogger();
if (log.isWarnEnabled())
{
log.warn("element2txt failed", e);
}
return null;
}
return sw.toString();
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
{
out.defaultWriteObject();
}
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
}
}