package org.seqcode.viz.paintable;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.awt.Dimension;
import java.awt.Color;
import java.io.File;
import java.io.Writer;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFileChooser;
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.dom.GenericDOMImplementation;
import org.seqcode.viz.components.ImageConfigurationFrame;
import org.w3c.dom.Document;
import org.w3c.dom.DOMImplementation;
public abstract class AbstractPaintable
implements Paintable, PaintableChangedListener {
private boolean imageRaster=true, disableEventPassthrough=false;
public static int sImageWidth, sImageHeight;
static {
sImageWidth = 1000;
sImageHeight = 750;
}
protected LinkedList<PaintableChangedListener> fListeners;
protected int siw, sih;
public AbstractPaintable() {
fListeners = new LinkedList<PaintableChangedListener>();
sih = sImageHeight;
siw = sImageWidth;
}
public AbstractPaintable(int h, int w) {
fListeners = new LinkedList<PaintableChangedListener>();
sih = h;
siw = w;
}
public boolean getImageRaster(){return(imageRaster);}
public void setImageRaster(boolean ir){imageRaster=ir;}
public void setImageWidth(int iw) { siw = iw; }
public void setImageHeight(int ih) { sih = ih; }
public abstract void paintItem(Graphics g, int x1, int y1, int x2, int y2);
public Collection<Action> getPaintableActions() {
LinkedList<Action> lst = new LinkedList<Action>();
lst.addLast(getSaveImageAction());
lst.addLast(getImageSettingsAction());
return lst;
}
public Action getSaveImageAction() {
return(getSaveImageAction("Save Image"));
}
public Action getSaveImageAction(String message) {
return new AbstractAction(message) {
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
String pwdName = System.getProperty("user.dir");
JFileChooser chooser;
if(pwdName != null) {
chooser = new JFileChooser(new File(pwdName));
} else {
chooser = new JFileChooser();
}
int v =
chooser.showSaveDialog(null);
if(v == JFileChooser.APPROVE_OPTION) {
File f = chooser.getSelectedFile();
try {
saveImage(f, sImageWidth, sImageHeight, imageRaster);
//System.out.println("Saved Image [" + sImageWidth + " by " + sImageHeight + "]");
} catch(IOException ie) {
ie.printStackTrace(System.err);
}
}
}
};
}
public Action getImageSettingsAction(){
final AbstractPaintable p = this;
return new AbstractAction("Image Settings..."){
public void actionPerformed(ActionEvent e) {
new ImageConfigurationFrame(p);
}
};
}
public void registerClick(double xf, double yf) {
}
protected void setEventPassthrough(boolean v) {
disableEventPassthrough = !v;
}
public void paintableChanged(PaintableChangedEvent evt) {
if(!disableEventPassthrough) {
dispatchChangedEvent();
}
}
public void addPaintableChangedListener(PaintableChangedListener l) {
fListeners.addLast(l);
}
public void removePaintableChangedListener(PaintableChangedListener l) {
fListeners.remove(l);
}
public Image createImage(int w, int h) {
BufferedImage im =
new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = im.getGraphics();
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
paintItem(g, 0, 0, w, h);
return im;
}
public void saveImage(File f, int w, int h, boolean raster)
throws IOException {
if (raster) {
BufferedImage im =
new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = im.getGraphics();
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
paintItem(g, 0, 0, w, h);
ImageIO.write(im, "png", f);
} else {
DOMImplementation domImpl =
GenericDOMImplementation.getDOMImplementation();
// Create an instance of org.w3c.dom.Document
Document document = domImpl.createDocument(null, "svg", null);
// Create an instance of the SVG Generator
SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
svgGenerator.setSVGCanvasSize(new Dimension(w,h));
// Ask the test to render into the SVG Graphics2D implementation
svgGenerator.setColor(Color.white);
svgGenerator.fillRect(0,0,w,h);
paintItem(svgGenerator,25,25,w-50,h-50);
// Finally, stream out SVG to the standard output using UTF-8
// character to byte encoding
boolean useCSS = true; // we want to use CSS style attribute
Writer out = new OutputStreamWriter(new FileOutputStream(f), "UTF-8");
svgGenerator.stream(out, useCSS);
}
}
protected void dispatchChangedEvent() {
PaintableChangedEvent evt = new PaintableChangedEvent(this);
for(PaintableChangedListener l : fListeners) {
l.paintableChanged(evt);
}
}
}