--- /dev/null
+package tim.prune.gui;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import javax.swing.ImageIcon;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import tim.prune.I18nManager;
+import tim.prune.data.Photo;
+
+/**
+ * GUI component for showing photo thumbnail
+ */
+public class PhotoThumbnail extends JPanel implements Runnable
+{
+ private Photo _photo = null;
+ private Image _thumbnail = null;
+ private boolean _loadingImage = false;
+ 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") + " ...";
+
+
+ /**
+ * Constructor
+ */
+ public PhotoThumbnail()
+ {
+ this(true);
+ }
+
+ /**
+ * Constructor
+ * @param inPanel true if thumbnail is inside panel
+ */
+ public PhotoThumbnail(boolean inPanel)
+ {
+ setOpaque(true);
+ _inPanel = inPanel;
+ }
+
+ /**
+ * Set the Photo
+ * @param inPhoto Photo object to show thumbnail for
+ */
+ public void setPhoto(Photo inPhoto)
+ {
+ // Check whether the photo has changed
+ if (_photo != inPhoto)
+ {
+ _photo = inPhoto;
+ _thumbnail = null;
+ _loadFailed = false;
+ }
+ repaint();
+ }
+
+ /**
+ * Force a refresh / reload
+ */
+ public void refresh()
+ {
+ _thumbnail = null;
+ _loadFailed = false;
+ }
+
+ /**
+ * Override paint method
+ * @see javax.swing.JComponent#paint(java.awt.Graphics)
+ */
+ public void paint(Graphics inG)
+ {
+ super.paint(inG);
+ if (_photo != null)
+ {
+ // read thumbnail in separate thread
+ if (_thumbnail == null && !_loadingImage && !_loadFailed)
+ {
+ _loadingImage = true;
+ new Thread(this).start();
+ }
+ // if loading, display message
+ if (_loadingImage)
+ {
+ inG.setColor(Color.BLACK);
+ inG.drawString(LOADING_STRING, 10, 30);
+ }
+ else if (_thumbnail != null && !_loadFailed)
+ {
+ // 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();
+ }
+ });
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Run method, for loading image in separate thread
+ * @see java.lang.Runnable#run()
+ */
+ public void run()
+ {
+ if (_inPanel)
+ {
+ _thumbnail = null;
+ // try to use exif thumbnail
+ 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;
+ }
+ // Maybe there's no thumbnail, maybe the load of the thumbnail failed
+ if (_thumbnail == null)
+ {
+ // 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();
+ }
+}