/*
* Author: tdanford
* Date: May 18, 2008
*/
/**
*
*/
package org.seqcode.viz.paintable;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
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;
/**
* @author tdanford
*
*/
public class DoubleBufferedPaintable implements Paintable, PaintableChangedListener {
private Paintable inner;
private BufferedImage buffer;
private int width, height;
private LinkedList<PaintableChangedListener> listeners;
private boolean paintBackground;
public DoubleBufferedPaintable(Paintable p) {
inner = p;
width = height = -1;
buffer = null;
paintBackground = false;
listeners = new LinkedList<PaintableChangedListener>();
inner.addPaintableChangedListener(this);
}
public void paintBackground(boolean bg) {
paintBackground = bg;
dispatchChangedEvent();
}
public void invalidateBuffer() {
buffer = null;
width = height = -1;
}
private void createNewBuffer(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));
if(paintBackground) {
g.setColor(Color.white);
g.fillRect(0, 0, w, h);
}
inner.paintItem(g, 0, 0, w, h);
width = w; height = h;
buffer = im;
}
public void paintableChanged(PaintableChangedEvent e) {
invalidateBuffer();
dispatchChangedEvent();
}
/* (non-Javadoc)
* @see org.seqcode.viz.paintable.Paintable#addPaintableChangedListener(org.seqcode.viz.paintable.PaintableChangedListener)
*/
public void addPaintableChangedListener(PaintableChangedListener l) {
listeners.add(l);
}
protected void dispatchChangedEvent() {
PaintableChangedEvent evt = new PaintableChangedEvent(this);
for(PaintableChangedListener listener : listeners) {
listener.paintableChanged(evt);
}
}
/* (non-Javadoc)
* @see org.seqcode.viz.paintable.Paintable#getPaintableActions()
*/
public Collection<Action> getPaintableActions() {
return inner.getPaintableActions();
}
/* (non-Javadoc)
* @see org.seqcode.viz.paintable.Paintable#getSaveImageAction()
*/
public Action getSaveImageAction() {
return new AbstractAction("Save As Image...") {
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.showOpenDialog(null);
if(v == JFileChooser.APPROVE_OPTION) {
File f = chooser.getSelectedFile();
int w = width > 0 ? width : 800;
int h = height > 0 ? height : 600;
try {
saveImage(f, w, h, true);
System.out.println("Saved Image [" + width + " by " + height + "]");
} catch(IOException ie) {
ie.printStackTrace(System.err);
}
}
}
};
}
protected void saveImage(File f, int w, int h, boolean b) throws IOException {
if(buffer == null || w != width || h != height) {
createNewBuffer(w, h);
}
ImageIO.write(buffer, "png", f);
}
/* (non-Javadoc)
* @see org.seqcode.viz.paintable.Paintable#paintItem(java.awt.Graphics, int, int, int, int)
*/
public void paintItem(Graphics g, int x1, int y1, int x2, int y2) {
int w = x2 - x1, h = y2 - y1;
if(buffer == null || w != width || h != height) {
createNewBuffer(w, h);
}
g.setColor(Color.white);
g.fillRect(0, 0, w, h);
g.drawImage(buffer, 0, 0, w, h, null);
}
/* (non-Javadoc)
* @see org.seqcode.viz.paintable.Paintable#registerClick(double, double)
*/
public void registerClick(double xf, double yf) {
inner.registerClick(xf, yf);
}
/* (non-Javadoc)
* @see org.seqcode.viz.paintable.Paintable#removePaintableChangedListener(org.seqcode.viz.paintable.PaintableChangedListener)
*/
public void removePaintableChangedListener(PaintableChangedListener l) {
listeners.remove(l);
}
}