View Javadoc

1   /*
2    * Copyright 2008 Google Inc.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    * 
8    * http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package org.utgenome.gwt.widget.client;
17  
18  import java.util.ArrayList;
19  
20  /**
21   * Provides a mechanism for deferred execution of a callback method once all specified Images are loaded.
22   */
23  public class ImageLoader {
24  
25  	/**
26  	 * Interface to allow anonymous instantiation of a CallBack Object with method that gets invoked when all the images
27  	 * are loaded.
28  	 */
29  	public interface CallBack {
30  		void onImagesLoaded(ImageHandle[] imageHandles);
31  	}
32  
33  	/**
34  	 * Static internal collection of ImageLoader instances. ImageLoader is not instantiable externally.
35  	 */
36  	private static ArrayList<ImageLoader> imageLoaders = new ArrayList<ImageLoader>();
37  
38  	/**
39  	 * Takes in an array of url Strings corresponding to the images needed to be loaded. The onImagesLoaded() method in
40  	 * the specified CallBack object is invoked with an array of ImageHandles corresponding to the original input array
41  	 * of url Strings once all the images report an onload event.
42  	 * 
43  	 * @param urls
44  	 *            Array of urls for the images that need to be loaded
45  	 * @param cb
46  	 *            CallBack object
47  	 */
48  	public static void loadImages(String[] urls, CallBack cb) {
49  		ImageLoader il = new ImageLoader();
50  		for (int i = 0; i < urls.length; i++) {
51  			il.addHandle(il.loadImage(urls[0]));
52  		}
53  		il.finalize(cb);
54  		ImageLoader.imageLoaders.add(il);
55  	}
56  
57  	private CallBack callBack = null;
58  	private ArrayList<ImageHandle> images = new ArrayList<ImageHandle>();
59  	private int loadedImages = 0;
60  	private int totalImages = 0;
61  
62  	private ImageLoader() {
63  	}
64  
65  	/**
66  	 * Stores the ImageHandle reference so that when all the images report an onload, we can return the array of all the
67  	 * ImageHandles.
68  	 * 
69  	 * @param img
70  	 */
71  	private void addHandle(ImageHandle img) {
72  		this.totalImages++;
73  		this.images.add(img);
74  	}
75  
76  	/**
77  	 * Invokes the onImagesLoaded method in the CallBack if all the images are loaded AND we have a CallBack specified.
78  	 * 
79  	 * Called from the JSNI onload event handler.
80  	 */
81  	private void dispatchIfComplete() {
82  		if (callBack != null && isAllLoaded()) {
83  			callBack.onImagesLoaded((ImageHandle[]) images.toArray(new ImageHandle[0]));
84  			// remove the image loader
85  			ImageLoader.imageLoaders.remove(this);
86  		}
87  	}
88  
89  	/**
90  	 * Sets the callback object for the ImageLoader. Once this is set, we may invoke the callback once all images that
91  	 * need to be loaded report in from their onload event handlers.
92  	 * 
93  	 * @param cb
94  	 */
95  	private void finalize(CallBack cb) {
96  		this.callBack = cb;
97  	}
98  
99  	private void incrementLoadedImages() {
100 		this.loadedImages++;
101 	}
102 
103 	private boolean isAllLoaded() {
104 		return (loadedImages == totalImages);
105 	}
106 
107 	/**
108 	 * Returns a handle to an img object. Ties back to the ImageLoader instance
109 	 */
110 	private native ImageHandle loadImage(String url)/*-{
111 		    // if( callback specified )
112 		    // do nothing
113 		     
114 		    var img = new Image();
115 		    var __this = this;
116 		     
117 		    img.onload = function() {
118 		      if(!img.__isLoaded) {
119 		       
120 		        // __isLoaded should be set for the first time here.
121 		        // if for some reason img fires a second onload event
122 		        // we do not want to execute the following again (hence the guard)
123 		        img.__isLoaded = true;       
124 		        __this.@org.utgenome.gwt.widget.client.ImageLoader::incrementLoadedImages()();
125 		        img.onload = null;
126 		        
127 		        // we call this function each time onload fires
128 		        // It will see if we are ready to invoke the callback
129 		        __this.@org.utgenome.gwt.widget.client.ImageLoader::dispatchIfComplete()();   
130 		      } 
131 		    }
132 		    
133 		    img.src = url;
134 		    
135 		    return img;
136 		  }-*/;
137 }