/*
* ThumbnailCell.java
*
* Created on December 18, 2002, 4:04 PM
*/
package kiyut.swing.shell.shelllistview;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.IOException;
import javax.imageio.*;
import javax.imageio.stream.*;
import javax.imageio.event.*;
import javax.swing.*;
import javax.swing.event.*;
import kiyut.swing.shell.image.ImageUtilities;
/**
* Thumbnail Cell that represent a cell in the <code>ThumbnailView</code> component
* @version 1.0
* @author tonny
*/
public class ThumbnailCell extends JComponent implements IIOReadUpdateListener, IIOReadProgressListener {
private static int IMAGE_WIDTH = 128;
private static int IMAGE_HEIGHT = 128;
/** label for this component */
protected JLabel label;
/** image pane or icon pane for this component */
protected ImagePane imagePane;
/** editor for this component */
protected JComponent editor;
/** cell has focus for this component */
protected boolean cellHasFocus = false;
/** boolean value for editing status */
protected boolean editing = false;
/** thumbnail view for this component */
protected ThumbnailView thumbnailView;
/** Image Loading progress */
protected float progress = 0;
/** Constructs a <code>ThumbnailCell</code> and initialize with the given parameter
* @param thumbnailView an <code>ThumbnailView</code> object
*/
public ThumbnailCell(ThumbnailView thumbnailView) {
this.thumbnailView = thumbnailView;
int width = 128;
imagePane = new ImagePane();
imagePane.setPreferredSize(new Dimension(width,128));
imagePane.setBorder(BorderFactory.createEtchedBorder());
imagePane.setOpaque(false);
label = new JLabel();
label.setPreferredSize(new Dimension(width,20));
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setVerticalAlignment(SwingConstants.TOP);
label.setLabelFor(imagePane);
label.setText("filename");
label.setOpaque(false);
this.setLayout(new BorderLayout());
this.add(imagePane, BorderLayout.CENTER);
this.add(label, BorderLayout.SOUTH);
}
/** invoked to draw this component
* @param g the Graphics context in which to paint
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
label.setFont(thumbnailView.getFont());
Insets insets = getInsets();
int x = insets.left;
int y = insets.top;
int w = getWidth() - insets.left - insets.right;
int h = getHeight() - insets.top - insets.bottom;
if (editing) {
label.setForeground(thumbnailView.getForeground());
g.setColor(thumbnailView.getBackground());
g.fillRect(x,y,w,h);
} else {
if (cellHasFocus) {
label.setForeground(thumbnailView.getSelectionForeground());
g.setColor(thumbnailView.getSelectionBackground());
g.fillRect(x,y,w,h);
} else {
label.setForeground(thumbnailView.getForeground());
g.setColor(thumbnailView.getBackground());
g.fillRect(x,y,w,h);
}
}
}
/** set the text for this component to display
* if the value of text is null or empty string, nothing is displayed.
* @param text a string to display
*/
public void setText(String text) {
label.setText(text);
}
/** Returns the text string that the label displays.
* @return a String
*/
public String getText() {
return label.getText();
}
/** set the image for this component to display
* if the value of image is null or empty string, nothing is displayed.
* @param image the image to display
*/
public void setImage(BufferedImage image) {
imagePane.setImage(image);
}
/** return the image
* @return the image
*/
public BufferedImage getImage() {
return imagePane.getImage();
}
/** set the image rescale
* @param width the width to which to scale the image.
* @param height the height to which to scale the image.
*/
public void setImageRescale(double width, double height) {
imagePane.setImageRescale(width,height);
}
/** Sets the font for this component.
* @param font The font to become this component's font.
*/
public void setFont(Font font) {
setFont(font);
label.setFont(font);
}
/** set cell has focus
* @param cellHasFocus boolean value to set the focus of this component
*/
public void setCellHasFocus(boolean cellHasFocus) {
this.cellHasFocus = cellHasFocus;
}
/** return whether this component has focus or not
* @return true if this component has focus; otherwise false
*/
public boolean isCellHasFocus() {
return this.cellHasFocus;
}
/** Sets the editor to used by when this component is edited.
* @param editor the new cell editor
*/
public void setCellEditor(JComponent editor) {
this.editor = editor;
}
/** remove the cell editor used by this component */
public void removeCellEditor() {
this.editor = null;
}
/** Tells the editor to start editing
* @return true if editing was started; false otherwise
*/
public boolean startCellEditing() {
editing = true;
editor.setPreferredSize(label.getPreferredSize());
remove(label);
add(editor, BorderLayout.SOUTH);
editor.requestFocusInWindow();
return true;
}
/** Tells the editor to stop editing and accept any partially edited value as the value of the editor.
* @return true if editing was stopped; false otherwise
*/
public boolean stopCellEditing() {
editing = false;
this.remove(editor);
this.add(label, BorderLayout.SOUTH);
return true;
}
/** Read file image contained in the <code>reader</code>
* and register with this component <code>IIOReadUpdateListener</code>
* and <code>IIOReadProgressListener</code>
* @param reader <code>ImageReader</code> use to read the file
* @param param <code>ImageReadParam</code> for the reader
* @throws IOException If an I/O error occurs
*/
public BufferedImage readFileImage(ImageReader reader, ImageReadParam param) throws IOException {
int w = reader.getWidth(0);
int h = reader.getHeight(0);
Dimension size = imagePane.getPreferredSize();
Dimension dest = new Dimension((int)size.getWidth()-5,(int)size.getHeight()-5);
Dimension src = new Dimension(w,h);
double scale = ImageUtilities.scaleToFit(src,dest);
imagePane.setImageRescale(scale,scale);
reader.addIIOReadUpdateListener(this);
reader.addIIOReadProgressListener(this);
BufferedImage bi = reader.read(0,param);
reader.removeIIOReadUpdateListener(this);
reader.removeIIOReadProgressListener(this);
// to converserve the memory, once the loading done,
// resize the big image into the smaller version
BufferedImage smallImg = ImageUtilities.scaleImageToFit(bi,IMAGE_WIDTH,IMAGE_HEIGHT,this);
w = smallImg.getWidth();
h = smallImg.getHeight();
size = imagePane.getPreferredSize();
dest = new Dimension((int)size.getWidth()-5,(int)size.getHeight()-5);
src = new Dimension(w,h);
scale = ImageUtilities.scaleToFit(src,dest);
setImage(smallImg);
setImageRescale(scale,scale);
repaint();
return bi;
}
/** {@inheritDoc} */
public void imageUpdate(ImageReader source, BufferedImage theImage, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) {
//imagePane.paintImmediately(minX,minY,width,height);
//repaint();
}
/** {@inheritDoc} */
public void passComplete(ImageReader source, BufferedImage theImage) {
}
/** {@inheritDoc} */
public void passStarted(ImageReader source, BufferedImage theImage, int pass, int minPass, int maxPass, int minX, int minY, int periodX, int periodY, int[] bands) {
//imagePane.setImage(theImage);
if (pass == 0) {
imagePane.setImage(theImage);
repaint();
}
}
/** {@inheritDoc} */
public void thumbnailPassComplete(ImageReader source, BufferedImage theThumbnail) {
}
/** {@inheritDoc} */
public void thumbnailPassStarted(ImageReader source, BufferedImage theThumbnail, int pass, int minPass, int maxPass, int minX, int minY, int periodX, int periodY, int[] bands) {
}
/** {@inheritDoc} */
public void thumbnailUpdate(ImageReader source, BufferedImage theThumbnail, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) {
}
/** {@inheritDoc} */
public void imageComplete(ImageReader source) {
}
/** {@inheritDoc} */
public void imageProgress(ImageReader source, float percentageDone) {
if ((percentageDone - progress) >= 10) {
repaint();
progress = percentageDone;
}
}
/** {@inheritDoc} */
public void imageStarted(ImageReader source, int imageIndex) {
progress = 0;
}
/** {@inheritDoc} */
public void readAborted(ImageReader source) {
}
/** {@inheritDoc} */
public void sequenceComplete(ImageReader source) {
}
/** {@inheritDoc} */
public void sequenceStarted(ImageReader source, int minIndex) {
}
/** {@inheritDoc} */
public void thumbnailComplete(ImageReader source) {
}
/** {@inheritDoc} */
public void thumbnailProgress(ImageReader source, float percentageDone) {
}
/** {@inheritDoc} */
public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {
}
/** A component for the parent class to render an image */
private class ImagePane extends JPanel {
/** an image for this component */
private BufferedImage image;
/** the scale with for this component. */
private double scaleWidth = 1.0;
/** the scaleHeight for this component. */
private double scaleHeight = 1.0;
/** Constructs a <code>ImagePane</code> */
public ImagePane() { }
/** set the image for this component to display
* if the value of image is null or empty string, nothing is displayed.
* @param image the image to display
*/
public void setImage(BufferedImage image) {
this.image = image;
}
/** set the image rescale
* @param width the width to which to scale the image.
* @param height the height to which to scale the image.
*/
public void setImageRescale(double width, double height) {
this.scaleWidth = width;
this.scaleHeight = height;
}
/** return the image
* @return the image
*/
public BufferedImage getImage() {
return image;
}
/** invoked to draw this component
* @param g the Graphics context in which to paint
*/
public void paintComponent(Graphics g) {
super.paintComponent(g); // paint background
if (image == null) {
return;
}
Graphics2D g2 = (Graphics2D) g;
double w = image.getWidth() *scaleWidth;
double h = image.getHeight() *scaleHeight;
Dimension dim = getSize();
double x = 0;
double y = 0;
if (dim.getWidth() > w) {
x = (dim.getWidth() - w)/2;
}
if (dim.getHeight() > h) {
y = (dim.getHeight() - h)/2;
}
g2.drawImage(image,(int)x,(int)y,(int)w,(int)h,this);
}
}
}