View Javadoc
1   package net.sourceforge.jsh3modtool.gui.imagetable.cache;
2   
3   import java.awt.Image;
4   import java.awt.image.BufferedImage;
5   import java.util.*;
6   import java.util.Map.Entry;
7   
8   import net.sourceforge.jsh3modtool.gui.imagetable.ImageCell;
9   import net.sourceforge.jsh3modtool.gui.imagetable.ImageModel;
10  
11  /***
12   * A very simple image cache stuff.
13   *
14   * @author  erma
15   */
16  public class ImageCache implements ThumbnailViewer
17  {
18      private int     loadingImagesMax = 50;
19      private Map     loadingImagesLookupTable;
20      private ImageLoadingListener imageLoadingListener;
21          
22      private int     cachedImagesMax;
23      private int     cachedImagesCount;
24      private Map     cache;
25  
26      /*** 
27       * Creates a new instance of ImageBrowserCache
28       * @param listener a image loading listener. 
29       */
30      public ImageCache(ImageLoadingListener listener)
31      {
32          this( listener, 200 );
33      }
34      
35      /*** 
36       * Creates a new instance of ImageBrowserCache
37       * @param listener a image loading listener.
38       * @param cacheMax the maximum number of images to cache. 
39       */
40      public ImageCache(ImageLoadingListener listener, int cacheMax)
41      {
42          cachedImagesMax = cacheMax;
43          cache = Collections.synchronizedMap(new ImageCacheMap( cachedImagesMax, 0.75f ) );
44          loadingImagesLookupTable = Collections.synchronizedMap( new Hashtable() );
45          imageLoadingListener = listener;
46      }
47      
48      /***
49       * Returns the number of cached images.
50       * @return the number of cached images.
51       */
52      public int getCachedImagesCount()
53      {
54          return cachedImagesCount;
55      }
56      
57      /***
58       * Returns the cached image for the specified image, can be null.
59       * @param imageCell the image cell to get the cached image for.
60       * @return the cached image for the specified image, can be null.
61       */
62      public BufferedImage getImage( ImageCell imageCell )
63      {  
64          BufferedImage image = null;
65          if ( imageCell != null )
66          {
67              image = (BufferedImage) cache.get( imageCell.getImageModel() );
68              if (( image == null ) && (!imageCell.hasTriedToLoadImage()))
69              {
70                  loadTableImage( imageCell );
71              }
72          }
73          return image;
74      }
75      
76      /***
77       * Loads the table image for thumbnailloader.
78       * @param imageCell the image cell to load an image for.
79       */
80      private void loadTableImage( ImageCell imageCell )
81      {
82          ImageModel imageModel = imageCell.getImageModel();
83          ThumbnailLoader loader = ThumbnailLoader.instance();
84          
85          if ( ! loader.contains( imageModel ) )
86          {
87              loadingImagesLookupTable.put( imageModel, imageCell );            
88              loader.addFirst( imageModel, this );
89              
90              if ( loader.queueSize() > loadingImagesMax )
91              {
92                  loader.removeLast();
93              }
94          } 
95          else
96          {
97              loader.increasePriority( imageModel );
98          }
99      }
100     
101     /***
102      * Tells the cache to reload the cached image.
103      * The cache will keep the old image until the new one has been loaded.
104      * When the new image has been loaded it will replace the cached and the
105      * cell with be updated.
106      * @param imageCell the cell that needs a new image.
107      */
108     public void reloadCachedImage( ImageCell imageCell )
109     {
110         loadTableImage( imageCell );
111     }
112     
113     /***
114      * Returns if the tableimage is cached or not.
115      * @param imageCell the lookup object.
116      * @return if the tableimage is cached or not.
117      */
118     public boolean isCached( ImageCell imageCell )
119     {
120         return cache.containsKey(imageCell.getImageModel());
121     }
122     
123     /***
124      * Clears the cache.
125      */
126     public void clear()
127     {
128         ThumbnailLoader.instance().clear();
129         cache.clear();
130         loadingImagesLookupTable.clear();
131         cachedImagesCount = 0;
132     }
133     
134     /***
135      * Removes the cached images for the files in the list. 
136      * @param files list containing File objects.
137      */
138     /*void clearCachedFiles(List files)
139     {
140         for ( Iterator iterator = files.iterator(); iterator.hasNext(); )
141         {
142             File file = (File) iterator.next();
143             cache.remove(file.getAbsolutePath());
144         }
145     }*/
146     
147     /***
148      * Clears the cached image from the cache.
149      * @param imageCell the image cells cached image to remove.
150      */
151     public void removeCachedImage( ImageCell imageCell )
152     {
153         cache.remove(imageCell.getImageModel());
154     }
155     
156     /*** {@inheritDoc} */
157     private void cacheImage( ImageCell imageCell, Image image )
158     {
159         if ( ( imageCell.getImageModel() != null ) && ( image != null ) )
160         {   
161             cache.put( imageCell.getImageModel(), image );
162             cachedImagesCount++;
163         }
164         imageLoadingListener.imageIsLoaded( imageCell );
165     }
166 
167     /*** {@inheritDoc} */
168     public void setImage(ImageModel imageModel, Image image)
169     {
170         ImageCell imageCell = (ImageCell) loadingImagesLookupTable.get( imageModel );        
171         loadingImagesLookupTable.remove( imageModel );
172         
173         if ( imageCell != null )
174         {
175             cacheImage( imageCell, image );
176         }
177     }
178     
179     /*** {@inheritDoc} */
180     public void setMessage(ImageModel imageModel, String msg)
181     {
182         ImageCell tableImage = (ImageCell) loadingImagesLookupTable.get( imageModel );
183         
184         if ( tableImage != null )
185         {
186             loadingImagesLookupTable.remove( imageModel );
187             tableImage.setHasTriedToLoadImage( true );
188             tableImage.setErrorMessage( msg );
189             imageLoadingListener.imageIsLoaded( tableImage );
190         }
191     }
192     
193     /***
194      * A linkedhashmap that removes the eldest entry if the size exceeds a number.
195      * @author erma
196      */
197     private class ImageCacheMap extends LinkedHashMap
198     {
199         /***
200          * Creates an ImageCacheMap with a set initialCapacity and loadFactor. 
201          * @param initialCapacity the initial capacity. 
202          * @param loadFactor the load factor.
203          */
204         protected ImageCacheMap(int initialCapacity, float loadFactor)
205         {
206             super(initialCapacity, loadFactor, true);
207         }
208         
209         /*** {@inheritDoc} */
210 		protected boolean removeEldestEntry(Entry eldest)
211 		{
212             return size() > cachedImagesMax;
213 		}
214     }
215 }