package org.rr.commons.swing.dialogs;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import org.rr.commons.utils.ReflectionFailureException;
import org.rr.commons.utils.ReflectionUtils;
public class JImageFileChooser extends JFileChooser {
private static final long serialVersionUID = 1456173962722237346L;
public JImageFileChooser() {
super();
ImagePreviewPanel imagePreviewPanel = new ImagePreviewPanel();
setAccessory(imagePreviewPanel);
addPropertyChangeListener(imagePreviewPanel);
}
/**
* Get the return value from a previous showOpenDialog call.
* @return The desired return value. (CANCEL_OPTION or APPROVE_OPTION ...)
*/
public int getReturnValue() {
try {
return ((Integer) ReflectionUtils.getFieldValue(this, "returnValue", false)).intValue();
} catch (ReflectionFailureException e) {
throw new RuntimeException(e);
}
}
private static class ImagePreviewPanel extends JPanel implements PropertyChangeListener {
private static final long serialVersionUID = 3262711734796955424L;
private int width, height;
private ImageIcon icon;
private Image image;
private static final int ACCSIZE = 155;
private Color bg;
public ImagePreviewPanel() {
setPreferredSize(new Dimension(ACCSIZE, -1));
bg = getBackground();
}
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
// Make sure we are responding to the right event.
if (propertyName.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
File selection = (File) e.getNewValue();
String name;
if (selection == null)
return;
else
name = selection.getAbsolutePath();
/*
* Make reasonably sure we have an image format that AWT can handle so we don't try to draw something silly.
*/
if ((name != null) && name.toLowerCase().endsWith(".jpg") || name.toLowerCase().endsWith(".jpeg") || name.toLowerCase().endsWith(".gif")
|| name.toLowerCase().endsWith(".png")) {
icon = new ImageIcon(name);
image = icon.getImage();
scaleImage();
repaint();
}
}
}
private void scaleImage() {
width = image.getWidth(this);
height = image.getHeight(this);
double ratio = 1.0;
/*
* Determine how to scale the image. Since the accessory can expand vertically make sure we don't go larger than 150 when scaling vertically.
*/
if (width >= height) {
ratio = (double) (ACCSIZE - 5) / width;
width = ACCSIZE - 5;
height = (int) (height * ratio);
} else {
if (getHeight() > 150) {
ratio = (double) (ACCSIZE - 5) / height;
height = ACCSIZE - 5;
width = (int) (width * ratio);
} else {
ratio = (double) getHeight() / height;
height = getHeight();
width = (int) (width * ratio);
}
}
if(width>0 && height>0) {
image = image.getScaledInstance(width, height, Image.SCALE_DEFAULT);
}
}
public void paintComponent(Graphics g) {
g.setColor(bg);
/*
* If we don't do this, we will end up with garbage from previous images if they have larger sizes than the one we are currently drawing. Also, it seems
* that the file list can paint outside of its rectangle, and will cause odd behavior if we don't clear or fill the rectangle for the accessory before
* drawing. This might be a bug in JFileChooser.
*/
g.fillRect(0, 0, ACCSIZE, getHeight());
g.drawImage(image, getWidth() / 2 - width / 2 + 5, getHeight() / 2 - height / 2, this);
}
}
}