001         package com.croftsoft.core.awt.image;
002    
003         import java.awt.*;
004         import java.awt.image.BufferedImage;
005         import java.io.*;
006         import java.util.*;
007    
008         import com.croftsoft.core.lang.ClassLib;
009         import com.croftsoft.core.lang.NullArgumentException;
010    
011         /*********************************************************************
012         * Caches loaded images by file name.
013         *
014         * @version
015         *   2003-07-24
016         * @since
017         *   2002-02-05
018         * @author
019         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
020         *********************************************************************/
021    
022         public final class  ImageCache
023         //////////////////////////////////////////////////////////////////////
024         //////////////////////////////////////////////////////////////////////
025         {
026    
027         private final Map          imageMap;
028    
029         private final int          transparency;
030    
031         private final Component    component;
032    
033         private final ClassLoader  classLoader;
034    
035         private final String       mediaDir;
036    
037         //////////////////////////////////////////////////////////////////////
038         // Constructor methods
039         //////////////////////////////////////////////////////////////////////
040    
041         /*********************************************************************
042         * Main constructor.
043         *
044         * @see
045         *   java.util.WeakHashMap
046         *
047         * @param  imageMap
048         *
049         *   A Map of images keyed by filenames.  You may wish to consider
050         *   using a WeakHashMap instead of the default HashMap created by
051         *   the convenience constructor.
052         *********************************************************************/
053         public  ImageCache (
054           int          transparency,
055           Component    component,
056           ClassLoader  classLoader,
057           String       mediaDir,
058           Map          imageMap )
059         //////////////////////////////////////////////////////////////////////
060         {
061           this.transparency = transparency;
062    
063           this.component    = component;
064    
065           this.classLoader  = classLoader;
066    
067           this.mediaDir     = mediaDir;
068    
069           NullArgumentException.check ( this.imageMap = imageMap );
070         }
071    
072         public  ImageCache (
073           int          transparency,
074           Component    component,
075           ClassLoader  classLoader,
076           String       mediaDir )
077         //////////////////////////////////////////////////////////////////////
078         {
079           this ( transparency, component, classLoader, mediaDir,
080             new HashMap ( ) );
081         }
082    
083         /*********************************************************************
084         * Convenience constructor.
085         *********************************************************************/
086         public  ImageCache ( Map  imageMap )
087         //////////////////////////////////////////////////////////////////////
088         {
089           this (
090             0,
091             ( Component   ) null,
092             ( ClassLoader ) null,
093             ( String      ) null,
094             imageMap );
095         }
096    
097         /*********************************************************************
098         * Convenience constructor.
099         *
100         * this(new HashMap());
101         *********************************************************************/
102         public  ImageCache ( )
103         //////////////////////////////////////////////////////////////////////
104         {
105           this ( new HashMap ( ) );
106         }
107    
108         //////////////////////////////////////////////////////////////////////
109         //////////////////////////////////////////////////////////////////////
110    
111         public void  clear ( )
112         //////////////////////////////////////////////////////////////////////
113         {
114           imageMap.clear ( );
115         }
116    
117         public boolean  containsKey ( String  imageFilename )
118         //////////////////////////////////////////////////////////////////////
119         {
120           return imageMap.containsKey ( imageFilename );
121         }
122    
123         public BufferedImage  get ( String  imageFilename )
124           throws IOException
125         //////////////////////////////////////////////////////////////////////
126         {
127           BufferedImage  image
128             = ( BufferedImage ) imageMap.get ( imageFilename );
129    
130           if ( ( image       == null )
131             && ( component   != null )
132             && ( classLoader != null ) )
133           {
134             image = ImageLib.loadAutomaticImage (
135               mediaDir == null ? imageFilename : mediaDir + imageFilename,
136               transparency,
137               component,
138               classLoader,
139               ( Dimension ) null );
140    
141             imageMap.put ( imageFilename, image );
142           }
143    
144           return image;
145         }
146    
147         public Image  remove ( String  imageFilename )
148         //////////////////////////////////////////////////////////////////////
149         {
150           return ( Image ) imageMap.remove ( imageFilename );
151         }
152    
153         /*********************************************************************
154         * Validates the image.
155         *
156         * <p>
157         * Checks to see if the image is already loaded.  If not, loads the
158         * file as a class resource byte stream and converts to an image.
159         * If component is not null, creates a MediaTracker to wait until the
160         * image is completely loaded before returning.
161         * </p>
162         *
163         * @see
164         *   java.awt.MediaTracker
165         *
166         * @see
167         *   com.croftsoft.core.lang.ClassLib#getResourceAsImage
168         *
169         * @param  imageFilename
170         *
171         *    The image filename and cache key.  Filenames are relative to
172         *    the root of the classpath or JAR file.
173         *    Example:  if the classpath is "J:\lib", this method would load
174         *    "/images/image.png" from "J:\lib\images\image.png".
175         *
176         * @param  component
177         *
178         *   If null, a MediaTracker will not be used to ensure load completion
179         *   before returning.
180         *
181         * @param  maxWaitTimeMs
182         *
183         *   The maximum time in milliseconds to wait for an image to finish
184         *   loading before returning.  Passed as the argument to
185         *   MediaTracker.waitForAll().
186         *********************************************************************/
187         public Image  validate (
188           String     imageFilename,
189           Component  component,
190           long       maxWaitTimeMs )
191           throws IOException, InterruptedException
192         //////////////////////////////////////////////////////////////////////
193         {
194           Image  image = ( Image ) imageMap.get ( imageFilename );
195    
196           if ( image == null )
197           {
198             image = ClassLib.getResourceAsImage (
199               ImageCache.class, imageFilename );
200    
201             imageMap.put ( imageFilename, image );
202    
203             if ( component != null )
204             {
205               MediaTracker  mediaTracker = new MediaTracker ( component );
206    
207               mediaTracker.addImage ( image, 0 );
208    
209               mediaTracker.waitForAll ( maxWaitTimeMs );
210             }
211           }
212    
213           return image;
214         }
215    
216         /*********************************************************************
217         * Validates the image without waiting to ensure load completion.
218         *
219         * Calls <code>validate(imageFilename,null,0)</code>.
220         *********************************************************************/
221         public Image  validate ( String  imageFilename )
222           throws IOException
223         //////////////////////////////////////////////////////////////////////
224         {
225           Image  image = null;
226    
227           try
228           {
229             image = validate ( imageFilename, null, 0 );
230           }
231           catch ( InterruptedException  ex )
232           {
233             // This code should never happen.
234    
235             ex.printStackTrace ( );
236           }
237    
238           return image;
239         }
240    
241         //////////////////////////////////////////////////////////////////////
242         //////////////////////////////////////////////////////////////////////
243         }