]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/gui/PhotoThumbnail.java
Version 19, May 2018
[GpsPrune.git] / tim / prune / gui / PhotoThumbnail.java
index b792a66f55b6b70ff820a8d539739fa51c096787..458ee8d84d866945d92d4cf51fb2b1da83ee5cd4 100644 (file)
@@ -4,9 +4,9 @@ import java.awt.Color;
 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;
@@ -17,11 +17,12 @@ 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") + " ...";
 
 
        /**
@@ -29,11 +30,18 @@ public class PhotoThumbnail extends JPanel implements Runnable
         */
        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
@@ -42,11 +50,23 @@ public class PhotoThumbnail extends JPanel implements Runnable
        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
@@ -57,29 +77,45 @@ public class PhotoThumbnail extends JPanel implements Runnable
                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();
+                                               }
+                                       });
+                               }
                        }
                }
        }
@@ -91,41 +127,40 @@ public class PhotoThumbnail extends JPanel implements Runnable
         */
        public void run()
        {
-               // Use exif thumbnail?
-               if (_photo.getExifThumbnail() != null) {
-                       Image image = new ImageIcon(_photo.getExifThumbnail()).getImage();
-                       _thumbnail = ImageUtils.createScaledImage(image, image.getWidth(null), image.getHeight(null));
-                       image = null;
-               }
-               else
+               if (_inPanel)
                {
-                       // no exif thumbnail available, going to have to read whole thing
-                       int picWidth = _photo.getWidth();
-                       int picHeight = _photo.getHeight();
-                       if (picWidth > -1 && picHeight > -1)
+                       _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)
                        {
-                               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)
+                               // 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 = new ImageIcon(_photo.getFile().getAbsolutePath()).getImage();
+                                       Image image = _photo.createImageIcon().getImage();
                                        // save scaled, smoothed thumbnail for reuse
                                        _thumbnail = ImageUtils.createScaledImage(image, thumbSize.width, thumbSize.height);
                                        image = null;
-                                       // TODO: Calculate and set size of thumbnail here
-                                       // setPreferredSize(new Dimension(200, 200));
                                }
+                               else _loadFailed = true;
                        }
                }
+               else {
+                       _thumbnail = _photo.createImageIcon().getImage();
+               }
                _loadingImage = false;
                repaint();
        }