001 /*
002 * Copyright 2002-2004 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.springframework.richclient.image;
017
018 import java.awt.Image;
019 import java.awt.Toolkit;
020 import java.awt.image.ImageObserver;
021 import java.io.File;
022 import java.io.IOException;
023 import java.io.InputStream;
024 import java.net.URL;
025
026 import org.springframework.core.io.AbstractResource;
027 import org.springframework.core.io.Resource;
028 import org.springframework.util.Assert;
029 import org.springframework.util.FileCopyUtils;
030
031 /**
032 * A resource decorator that represents an underlying graphical AWT image, such
033 * as a GIF, JPEG, or PNG.
034 *
035 * @author Keith Donald
036 */
037 public class AwtImageResource extends AbstractResource implements ImageObserver {
038 private Resource wrappedResource;
039
040 private boolean imageLoaded;
041
042 private boolean imageError;
043
044 public static final String RESOURCE_PREFIX = "image:";
045
046 /**
047 * Constructs a AwtImageResource for the following io.core.Resource. This
048 * assumes the wrapped resource actually points to a underlying image.
049 *
050 * @param resource
051 * The wrapped resource.
052 * @throws IllegalArgumentException,
053 * if the resource is invalid.
054 */
055 public AwtImageResource(Resource resource) {
056 Assert.notNull(resource);
057 if (resource instanceof AwtImageResource) {
058 throw new IllegalArgumentException("Wrapping another AwtImageResource instance is illegal.");
059 }
060 this.wrappedResource = resource;
061 }
062
063 public String getDescription() {
064 return wrappedResource.getDescription();
065 }
066
067 public Resource createRelative(String relativePath) throws IOException {
068 return wrappedResource.createRelative(relativePath);
069 }
070
071 public boolean exists() {
072 return wrappedResource.exists();
073 }
074
075 public boolean isOpen() {
076 return wrappedResource.isOpen();
077 }
078
079 public URL getURL() throws IOException {
080 return wrappedResource.getURL();
081 }
082
083 public File getFile() throws IOException {
084 return wrappedResource.getFile();
085 }
086
087 public String getFilename() throws IllegalStateException {
088 return wrappedResource.getFilename();
089 }
090
091 public InputStream getInputStream() throws IOException {
092 return wrappedResource.getInputStream();
093 }
094
095 /**
096 * Loads the image from the underlying <code>core.io.Resource.</code>
097 *
098 * This method does not cache. Calling it successively will result in a new
099 * image being loaded each time.
100 *
101 * @throws java.io.IOException
102 * If an error occurred while reading from the resource input
103 * stream.
104 */
105 public Image getImage() throws IOException {
106 return loadImage(getInputStream());
107 }
108
109 /**
110 * Load an image from the underlying resource's input stream. Constructs a
111 * new <code>Image</code> object from the data read from the input stream
112 * on each call.
113 * <p>
114 * This method loads the image fully into memory. This improves UI
115 * responsiveness when the image is needed by the GUI event-dispatching
116 * thread.
117 *
118 * @param stream
119 * The input stream.
120 * @return The resulting <code>Image</code> object.
121 * @throws java.io.IOException
122 * If an error occurred while reading from the stream.
123 */
124 private synchronized Image loadImage(InputStream stream) throws IOException {
125 Toolkit toolkit = Toolkit.getDefaultToolkit();
126 byte data[] = FileCopyUtils.copyToByteArray(stream);
127
128 Image image = toolkit.createImage(data);
129 imageLoaded = false;
130 imageError = false;
131 // fully loads the image into memory
132 toolkit.prepareImage(image, -1, -1, this);
133 while (!imageLoaded && !imageError) {
134 try {
135 wait();
136 }
137 catch (InterruptedException ex) {
138 }
139 }
140 if (imageError) {
141 throw new IOException("Error preparing image from resource.");
142 }
143 return image;
144 }
145
146 public synchronized boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
147 if ((infoflags & (ALLBITS | FRAMEBITS)) != 0) {
148 imageLoaded = true;
149 notifyAll();
150 }
151 else {
152 if ((infoflags & ERROR) != 0) {
153 imageError = true;
154 notifyAll();
155 }
156 }
157 return true;
158 }
159
160 public boolean equals(Object o) {
161 if (!(o instanceof AwtImageResource)) {
162 return false;
163 }
164 AwtImageResource r = (AwtImageResource)o;
165 return wrappedResource.equals(r.wrappedResource);
166 }
167
168 public int hashCode() {
169 return wrappedResource.hashCode();
170 }
171 }