import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
-import java.awt.image.BufferedImage;
-
import javax.swing.ImageIcon;
import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
import tim.prune.I18nManager;
import tim.prune.data.Photo;
public class PhotoThumbnail extends JPanel implements Runnable
{
private Photo _photo = null;
- private BufferedImage _thumbnail = null;
- private int _lastWidth = -1;
- private int _lastHeight = -1;
+ private Image _thumbnail = null;
private boolean _loadingImage = false;
- private static String _loadingString = null;
+ private boolean _loadFailed = false;
+ private boolean _inPanel = false;
+ /** String to show before photo is loaded */
+ private static final String LOADING_STRING = I18nManager.getText("details.photo.loading") + " ...";
/**
*/
public PhotoThumbnail()
{
- // TODO: Make size of thumbnail dynamic, as big as it can be
- setOpaque(true);
- _loadingString = I18nManager.getText("details.photo.loading") + " ...";
+ this(true);
}
+ /**
+ * Constructor
+ * @param inPanel true if thumbnail is inside panel
+ */
+ public PhotoThumbnail(boolean inPanel)
+ {
+ setOpaque(true);
+ _inPanel = inPanel;
+ }
/**
* Set the Photo
public void setPhoto(Photo inPhoto)
{
// Check whether the photo has changed
- if (_photo == inPhoto) {return;}
- _photo = inPhoto;
- _thumbnail = null;
+ if (_photo != inPhoto)
+ {
+ _photo = inPhoto;
+ _thumbnail = null;
+ _loadFailed = false;
+ }
+ repaint();
}
+ /**
+ * Force a refresh / reload
+ */
+ public void refresh()
+ {
+ _thumbnail = null;
+ _loadFailed = false;
+ }
/**
* Override paint method
super.paint(inG);
if (_photo != null)
{
- // recalculate thumbnail if photo has changed
- if (_thumbnail == null || getWidth() != _lastWidth || getHeight() != _lastHeight)
+ // read thumbnail in separate thread
+ if (_thumbnail == null && !_loadingImage && !_loadFailed)
{
- // initiate load if not already started
- if (!_loadingImage)
- {
- _loadingImage = true;
- new Thread(this).start();
- }
+ _loadingImage = true;
+ new Thread(this).start();
}
- // Set width and height
- _lastWidth = getWidth();
- _lastHeight = getHeight();
- // if loading, display image
+ // if loading, display message
if (_loadingImage)
{
inG.setColor(Color.BLACK);
- inG.drawString(_loadingString, 10, 30);
+ inG.drawString(LOADING_STRING, 10, 30);
}
- else
+ else if (_thumbnail != null && !_loadFailed)
{
- // Copy scaled, smoothed image onto the screen
- inG.drawImage(_thumbnail, 0, 0, _thumbnail.getWidth(), _thumbnail.getHeight(), null);
+ // Copy scaled, smoothed (and rotated) image into scaled
+ int usableWidth = getParent().getWidth()-10;
+ int usableHeight = (_inPanel?usableWidth:getHeight()-10);
+ Image scaled = ImageUtils.rotateImage(_thumbnail, usableWidth, usableHeight, _photo.getRotationDegrees());
+ int scaleWidth = scaled.getWidth(null);
+ int scaleHeight = scaled.getHeight(null);
+ // Draw scaled / rotated image to component
+ int horizOffset = (getWidth() - scaleWidth) / 2;
+ int vertOffset = (getHeight() - scaleHeight) / 2;
+ inG.drawImage(scaled, horizOffset, vertOffset, scaleWidth, scaleHeight, null);
+ // Special resize behaviour when locked inside details panel
+ if (_inPanel && (getHeight() < getWidth() || getHeight() > usableWidth))
+ {
+ Dimension newsize = new Dimension(usableWidth, usableWidth);
+ setPreferredSize(newsize);
+ setSize(newsize);
+ invalidate();
+ // Schedule a relayout because the size has changed
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ try {Thread.sleep(200);} catch (InterruptedException e) {}
+ getParent().getParent().getParent().validate();
+ }
+ });
+ }
}
}
}
*/
public void run()
{
- int picWidth = _photo.getWidth();
- int picHeight = _photo.getHeight();
- if (picWidth > -1 && picHeight > -1)
+ if (_inPanel)
{
- int displayWidth = Math.min(getWidth(), getParent().getWidth());
- // System.out.println("width = " + getWidth() + ", " + getParent().getWidth() + " = " + displayWidth);
- int displayHeight = Math.min(getHeight(), getParent().getHeight());
- // System.out.println("height = " + getHeight() + ", " + getParent().getHeight() + " = " + displayHeight);
-
- // calculate maximum thumbnail size
- Dimension thumbSize = ImageUtils.getThumbnailSize(picWidth, picHeight, displayWidth, displayHeight);
- // Work out if need to remake image
- boolean needToRemake = (_thumbnail == null)
- || _thumbnail.getWidth() != thumbSize.width || _thumbnail.getHeight() != thumbSize.height;
- if (thumbSize.width > 0 && thumbSize.height > 0 && needToRemake)
- {
- // Make icon to load image into
- Image image = new ImageIcon(_photo.getFile().getAbsolutePath()).getImage();
- // save scaled, smoothed thumbnail for reuse
- _thumbnail = ImageUtils.createScaledImage(image, thumbSize.width, thumbSize.height);
+ // use either exif thumbnail or photo scaled down to sensible size
+ if (_photo.getExifThumbnail() != null) {
+ // Use exif thumbnail
+ Image image = new ImageIcon(_photo.getExifThumbnail()).getImage();
+ _thumbnail = ImageUtils.createScaledImage(image, image.getWidth(null), image.getHeight(null));
image = null;
- // TODO: Calculate and set size of thumbnail here
- // setPreferredSize(new Dimension(200, 200));
}
+ else
+ {
+ // no exif thumbnail available, going to have to read whole thing
+ int picWidth = _photo.getWidth();
+ int picHeight = _photo.getHeight();
+ if (picWidth > -1 && picHeight > -1)
+ {
+ // Just set a "reasonable" thumbnail size for now
+ final int DEFAULT_THUMB_SIZE = 400;
+ // calculate maximum thumbnail size
+ Dimension thumbSize = ImageUtils.getThumbnailSize(picWidth, picHeight, DEFAULT_THUMB_SIZE, DEFAULT_THUMB_SIZE);
+ // Make icon to load image into
+ Image image = _photo.createImageIcon().getImage();
+ // save scaled, smoothed thumbnail for reuse
+ _thumbnail = ImageUtils.createScaledImage(image, thumbSize.width, thumbSize.height);
+ image = null;
+ }
+ else _loadFailed = true;
+ }
+ }
+ else {
+ _thumbnail = _photo.createImageIcon().getImage();
}
_loadingImage = false;
repaint();